Spaces:
Sleeping
Sleeping
| """ | |
| focal.py — Focal loss objective and eval for LightGBM. | |
| Extracted from sniper_v7_1.py so SniperModel can import them | |
| without depending on __main__. | |
| """ | |
| import numpy as np | |
| from scipy.special import expit | |
| # These are read from Config at training time; we keep the same defaults. | |
| FOCAL_GAMMA = 2.0 | |
| FOCAL_ALPHA = 0.25 | |
| def focal_loss_objective(y_pred, dtrain): | |
| y_true = dtrain.get_label() | |
| gamma = FOCAL_GAMMA | |
| alpha = FOCAL_ALPHA | |
| p = np.clip(expit(y_pred), 1e-7, 1 - 1e-7) | |
| p_t = np.where(y_true == 1, p, 1 - p) | |
| alpha_t = np.where(y_true == 1, alpha, 1 - alpha) | |
| log_p_t = np.log(p_t + 1e-10) | |
| dp_t_dz = np.where(y_true == 1, p * (1 - p), -p * (1 - p)) | |
| term1 = -gamma * log_p_t | |
| term2 = (1 - p_t) / (p_t + 1e-10) | |
| grad = -alpha_t * dp_t_dz * ((1 - p_t) ** (gamma - 1)) * (term1 + term2) | |
| abs_grad = np.abs(grad) | |
| hess = np.maximum(abs_grad * (2.0 - abs_grad), 1e-5) | |
| return grad, hess | |
| def focal_loss_eval(y_pred, dtrain): | |
| y_true = dtrain.get_label() | |
| p = np.clip(expit(y_pred), 1e-7, 1 - 1e-7) | |
| p_t = np.where(y_true == 1, p, 1 - p) | |
| alpha_t = np.where(y_true == 1, FOCAL_ALPHA, 1 - FOCAL_ALPHA) | |
| loss = -alpha_t * (1 - p_t) ** FOCAL_GAMMA * np.log(p_t + 1e-10) | |
| return "focal_loss", float(np.mean(loss)), False |