背景介绍
从DT到GBT,Xgboost,lightgbm,算法的稳定性和泛化能力在进一步的增加,之前的迭代方面主要集中在梯度提升和学习维度,以及降低模型的过拟合增加正则化,或者提升精度增加求导阶数。这些机器学习工具用于预测,且达到相当高的精确度,但也有些场景并没有特别大的把握能做出准确预测,如天气预测及寿命预测;另外自动决策系统尤其需要对不确定性的估计,以便提前做好备选方案应对;还有若在得到预测值的同时看到置信区间,如果真实值偏离预测值较远,但还落在该样本对应的置信区间内(只是置信区间也很大),则说明问题未必出现在模型上。(方便在跨部门/企业合作中撕的时候提供证据
仅仅是把标签值换成概率分布(的参数)并不能简单解决问题,于是为了做到“预测分布”这件事,作者引入更多相关数学概念对底层一番改造:
适当得分法则(Proper Scoring Rules)
NGBoost(Natural Gradient Boosting)是一种概率预测模型,它结合了梯度提升树和自然梯度下降的思想。NGBoost 的主要目标是通过预测目标变量的分布来提高预测精度,而不仅仅是预测一个点估计值(这里更多是针对回归问题,分类问题其他模型也可以支持)。
NGBoost 使用自然梯度下降来更新模型参数,可以减少训练过程中的振荡和收敛时间。自然梯度下降是梯度下降的变体,它使用 Fisher 信息矩阵来归一化梯度方向,以便在不同参数空间中进行更准确的更新。这种方法可以使得 NGBoost 更加鲁棒,并且具有更好的收敛性能。
1. 梯度提升(Gradient Boosting)
梯度提升是一种集成学习方法,它通过构建一系列的弱学习器(通常是决策树),并将它们以加权方式组合起来,来提高模型的预测性能。在每一步迭代中,新的弱学习器被添加到模型中,以最小化损失函数的梯度。
2. 自然梯度
自然梯度是一种在优化中使用的梯度,它考虑了参数空间中的度量结构。在传统的梯度下降中,使用的是欧几里得度量(即L2范数),而自然梯度则使用Fisher信息矩阵(或其逆)作为度量矩阵,从而考虑了参数间的依赖关系。这种方法可以使得优化过程更加高效,尤其是在参数空间具有复杂结构时。
3. NGBoost算法原理
NGBoost结合了上述两种思想:
模型构建:NGBoost使用一系列的弱学习器(通常是决策树),这些树在每一步迭代中根据当前模型的预测误差来构建。
自然梯度优化:在每一步迭代中,使用自然梯度而不是标准的梯度来更新模型的参数。自然梯度通过考虑Fisher信息矩阵(FIM)来调整梯度方向,使得优化过程更加高效和稳定。FIM是对参数的二阶导数进行估计,反映了参数间的相关性。
贝叶斯推断:NGBoost在内部使用贝叶斯推断框架来估计模型的参数和不确定性。这有助于生成预测的不确定性度量,例如预测的置信区间。
4. 优点
高效性:使用自然梯度可以减少在参数空间中的震荡,提高优化效率。
不确定性估计:通过贝叶斯方法,NGBoost能够提供模型预测的不确定性估计。
泛化能力:通过考虑参数间的依赖关系,NGBoost有助于提高模型的泛化能力。
5. 应用场景
NGBoost特别适用于需要高精度预测和不确定性估计的场景,如金融市场预测、医学诊断等。
ngboost建模
注意点:
(1)不支持类别型变量入模,需要自行编码
(2)不支持缺失数据入模,需要自行填充
(3)由于模型复杂度高,训练、推理速度减慢,不过通用参数效果依然很好
1、回归方面
from ngboost import NGBRegressor
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
# 生成数据
X, y = make_regression(n_samples=1000, n_features=20, noise=0.1, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建模型并训练
model = NGBRegressor(n_estimators=100, learning_rate=0.01)
model.fit(X_train, y_train)
# 评估模型
y_pred = model.predict(X_test)
2、分类方向
ngb_params={
'Dist':k_categorical(2), # 预测值y的分布,取值k_categorical, Bernoulli,Normal,Exponential等
'Score':LogScore, # 损失函数,取值LogScore, CRPScore
'Base':default_tree_learner, # 基学习器、类似于子树,取值default_tree_learner、DecisionTreeRegressor(criterion='friedman_mse', max_depth=4)
'natural_gradient':True, # 自然梯度 or 常规梯度
'n_estimators':1000, # 迭代次数
'learning_rate':0.01, # 学习速率
'minibatch_frac':1.0, # 行采样
'col_sample':1.0, # 列采样
'verbose':True,
'verbose_eval':100,
'tol':0.0001, # 迭代过程中损失函数阈值,当损失函数的变化小于tol时,训练过程将停止
'random_state':1,
}
def ngboost_model(df,y_name,fea_list,params):
x_train,x_test, y_train, y_test =train_test_split(df[fea_list],df[y_name],test_size=0.2, random_state=123)
model = NGBClassifier(**params)
model.fit(x_train, y_train)
train_pred = model.predict_proba(x_train)[:,1]
train_auc= roc_auc_score(list(y_train),train_pred)
test_pred = model.predict_proba(x_test)[:,1]
test_auc= roc_auc_score(list(y_test),test_pred)
result={
'train_auc':train_auc,
'test_auc':test_auc,
}
return model,result
ngboost_model,model_result=ngboost_model(df_copy.fillna(-1),'isDefault',float_col,ngb_params)
model_result