前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为风控业务定制损失函数与评价函数(XGB/LGB)

为风控业务定制损失函数与评价函数(XGB/LGB)

原创
作者头像
BBBlue
修改2019-12-23 11:49:32
2K0
修改2019-12-23 11:49:32
举报

XGBoost模型支持自定义评价函数损失函数。只要保证损失函数二阶可导,通过评价函数的最大化既可以对模型参数进行求解。实际使用中,可以考虑根据业务目标对这两者进行调整。

举个例子,假设现在有一个提额模型,用处是将分数最高的20%客户给与更高的额度。也就是期望分数最高的20%的客群正样本捕获率最大化。可能在保证上述前提,同时保证模型对正负样本有一定的区分能力。所以可以改写一个保证模型区分度,同时又能优化局部正样本捕获率的评价函数。

自定义XGBoost模型损失函数与评价函数。

代码语言:javascript
复制
# 自定义对数损失函数 
def loglikelood(preds, dtrain):  
    labels = dtrain.get_label()  
    preds = 1.0 / (1.0 + np.exp(-preds))  
    grad = preds - labels  
    hess = preds * (1.0-preds)  
    return grad, hess  
  
# 评价函数:前20%正样本占比最大化  
def binary_error(preds, train_data):  
    labels = train_data.get_label()  
    dct = pd.DataFrame({'pred':preds,'percent':preds,'labels':labels})  
    #取百分位点对应的阈值  
    key = dct['percent'].quantile(0.2)  
    #按照阈值处理成二分类任务  
    dct['percent']= dct['percent'].map(lambda x :1 if x <= key else 0)    
    #计算评价函数,权重默认0.5,可以根据情况调整  
    result = np.mean(dct[dct.percent== 1]['labels'] == 1)*0.5 
               + np.mean((dct.labels - dct.pred)**2)*0.5  
    return 'error',result  
  
watchlist  = [(dtest,'eval'), (dtrain,'train')]  
param = {'max_depth':3, 'eta':0.1, 'silent':1}  
num_round = 100  
# 自定义损失函数训练  
bst = xgb.train(param, dtrain, num_round, watchlist, loglikelood, binary_error)

可以看到评价函数由两部分组成,第一部分权重默认为0.5,目的是使得前20%样本中的正样本占比最大。因为正样本的标签为0,因此pandas.quantile()函数分位点参数0.2,表示预估为正样本概率最大的前20%分位点。第二部分权重同样默认设置为0.5,目的是让模型对正负样本的识别能力得到保障。

实际使用中,可以根据,对模型表现的侧重点,进行权重选择。比如当更希望模型关注于捕获率时,可以调整第一部分权重为0.8,将第二部分权重调整为0.2。本书给出的是一种启发性的思路,读者还可以根据实际情况改写更贴合业务的损失函数。

LightGBM中也同样支持自定义损失函数和评价函数。代码上有一些细微差别。评价函数需要返回三部分,用False代替。

代码语言:javascript
复制
 # 自定义二分类对数损失函数
def loglikelood(preds, train_data):
    labels = train_data.get_label()
    preds = 1. / (1. + np.exp(-preds))
    grad = preds - labels
    hess = preds * (1. - preds)
    return grad, hess

# 自定义前20%正样本占比最大化的评价函数
def binary_error(preds, train_data):
    labels = train_data.get_label()
    dct = pd.DataFrame({'pred':preds,'percent':preds,'labels':labels})
    #取百分位点对应的阈值
    key = dct['percent'].quantile(0.2)
    #按照阈值处理成二分类任务
    dct['percent']= dct['percent'].map(lambda x :1 if x <= key else 0)  
    #计算评价函数,权重默认0.5,可以根据情况调整
    result = np.mean(dct[dct.percent== 1]['labels'] == 1)*0.9 + np.mean((dct.labels - dct.pred)**2)*0.5
    return 'error',result, False

gbm = lgb.train(params,
                lgb_train,
                num_boost_round=100,
                init_model=gbm,
                fobj=loglikelood,
                feval=binary_error,
                valid_sets=lgb_eval)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档