机器学习中的早停策略

本文探讨了如何利用早停策略在LightGBM模型中避免过拟合和欠拟合,通过GridSearchCV进行参数调优,并介绍了HyperGBM的早停策略应用。核心内容包括验证集性能与迭代次数的关系、早停策略的实践、以及在时间限制和性能目标下的模型优化策略。
摘要由CSDN通过智能技术生成

前言

在做机器学习模型调优的时候,往往会通过一系列的操作去提升调优效率,其中有一种技术就是合理运用早停策略。

关于数据集:本文直接使用kaggle的数据集,你可以直接点击链接下载。

一、入门

1.验证集性能和迭代次数的关系

我们这里选用lightgbm算法作为演示,随机选择了一些参数值,然后设置n_estimators=1000,接下来我们来看一下验证集的性能和n_estimators的关系。

data = pd.read_csv('..\resource\data.csv',index_col=0)
Y = data.pop('target')
X = data
x_train,x_eval,y_train,y_eval = train_test_split(X,Y, test_size=0.2, random_state=623)

#模型训练
clf = lgb.LGBMClassifier(max_depth=4,n_estimators=1000,learning_rate=0.07)
clf.fit(x_train,y_train,eval_set=[(x_eval,y_eval)])

#获取验证集的结果
evals_results = clf.evals_result_['valid_0']['multi_logloss']

#画图
plt.plot(evals_results)
plt.vlines(100, 1.09, evals_results[100],color="red")
plt.vlines(np.argmin(evals_results), 1.09, evals_results[np.argmin(evals_results)],color="red")
plt.vlines(800, 1.09, evals_results[800],color="red")
plt.title('eval_metric_curve')
plt.xlabel('n_estimators')
plt.ylabel('multi_logloss')
plt.ylim(1.09,1.13)
plt.show()

在这里插入图片描述
从上面的结果图上我们可以看到,在实际训练的过程当中,如果只训练到第一根红线的位置,明显模型欠拟合,如果一直训练下去,训练到第三根红线的时候,明显模型过拟合了,最好的位置是第二根红线所在的位置,这时候,模型在验证集上的性能最优。

2. 引入早停策略

如上面分析,如果训练时间过短,模型还没有收敛,如果训练时间过长,模型开始过拟合,这个时候我们可以在fit阶段加入early_stopping_rounds参数,整体代码修改如下:

#省略相同代码
clf = lgb.LGBMClassifier(max_depth=4,n_estimators=1000,learning_rate=0.07)
clf.fit(x_train,y_train,eval_set=[(x_eval,y_eval)],early_stopping_rounds=50)
evals_results = clf.evals_result_['valid_0']['multi_logloss']
plt.plot(evals_results)
plt.title('eval_metric_curve')
plt.xlabel('n_estimators')
plt.ylabel('multi_logloss')
plt.show()
print('best training score:',min(evals_results))

scorer=get_scorer('neg_log_loss')
score = scorer(clf,x_eval,y_eval)
print('finnal model score:',score*scorer._sign)

在这里插入图片描述
同时使用了早停策略之后,模型会直接使用过程中最优的模型,如下图所示:
在这里插入图片描述

对比如果不使用早停策略的话,使用的是最终的一个过拟合模型,如下图所示:
在这里插入图片描述

二、进阶

以上介绍的是单个模型在训练的时候,我们一般可以使用较大的n_estimators+early_stopping_rounds进行模型的训练,但是在实际项目当中,还会涉及到模型如何调优的问题,这里我们以常见的GridSearchCV来演示一下。

这里我们基于上面的内容,继续来探索最优的几个其他参数,代码如下:


from sklearn.model_selection import GridSearchCV
#这里省略掉相同部分的代码
# ...
lightgbm_param_grid = {"max_depth":[3,4,5],
                       "num_leaves" : [20,31,50],
                       "reg_alpha":[0.1,0.5,1],
                       "reg_lambda":[0.001,0.005,0.01]
                       }
clf = lgb.LGBMClassifier(n_estimators=300,learning_rate=0.07)
Gclf = GridSearchCV(clf,param_grid = lightgbm_param_grid, cv=5, scoring="neg_log_loss",n_jobs= 4,verbose = 1)
Gclf.fit(x_train,y_train)
print(Gclf.best_params_)

通过上面的代码,我们可以进一步去获取最优的lightgbm参数,但是需要考虑到这里训练总次数一共是
参数组合(81) * 交叉验证(5) = 405次的训练次数。那这里又会出现一些新的需求

1. 在指定时间内搜索

老板刚刚给我打电话,说你现在手上的模型明天就得正式提测,那对于我来说,我就只有一个晚上的时间可以进行最后的调参了,所以我不得不考虑到我总共只有10h小时的时间了,那么上面的代码需要进行如下修改(伪代码)。

with Timer as Searching:
	这里还是做原来的参数调优
	if Searching.duration > 10*60*60:
		搜索超过10h,结束整个任务,然后保存最优的模型参数

这样一来,第二天早上九点我可以直接得到最优参数,然后进行提测(不然可能你会发现第二天你来了,程序还在运行,停止的话,什么都没有了,不停止的话,测试部已经开始在催你了)

2. 模型达到某一性能即可

两周前我们的模型的最优性能是98.6%的准确度,这个时候客户很满意我们的性能,然后告诉我们后天正式下单,这个时候,我的老板走过来告诉我,这可是一个大客户,你现在还有一点时间,你在调优调优,争取让性能突破98.6%的水平,给客户留下一个好印象,那这个时候我就想着在尝试尝试呗,看一下性能能不能继续突破98.8%,那整体代码设计修改如下:

In search step:
 if 当前模型的性能超过98.8%:
 	停止整个程序,保存最优模型性能

3. 连续N次性能都没有提升

机器学习的性能瓶颈往往不在于模型参数,而在于你提供的数据特征是什么水平(而想要做出非常优秀的特征,往往又需要对实际业务非常了解),所以尽管在时间充裕的情况下,一直进行参数调优的意义其实不会太大。所以可能会出现你用2h和用8h进行参数搜索的最终结果是一样的情况,那这个时候我们可以修改我们的整体代码如下:

In search step:
 if 当前模型性能 < 历史模型最优性能:
 	统计当前已经多少轮性能没有进一步提升了
 	if 轮数 > 阈值:
 		停止整个程序,保存最优模型

备注:连续N次性能都没有提升一般不适用于网格搜索,因为网格搜索搜索效率不会随着搜索次数的增多而提升,而对于常见的贝叶斯优化,遗传搜索算法,随着先验知识的累计,搜索效率是会提升的。

附:建模技巧

还是以上面的数据集为例,我们上面入门篇的时候,得到的模型最优性能是1.10013,现在我们尝试使用hypergbm[https://github.com/DataCanvasIO/HyperGBM],来进一步提升模型的性能。

在hypergbm中,支持的早停策略如下:
在这里插入图片描述

##首先是安装hypergbm
#pip install hypergbm

from sklearn.model_selection import train_test_split
from hypergbm import make_experiment
from sklearn.metrics import get_scorer


##导入数据
data = pd.read_csv('..\resource\data.csv',index_col=0)
df_trian,df_test = train_test_split(data, test_size=0.2, random_state=623)
target = 'target'

## 限制整个搜索时间为10h
exp1 = make_experiment(df_train,
					 target=target,
					 log_level='info',
					 max_trilas=10000, #使用早停策略,总搜索次数可以设置得足够大,默认为10
					 early_stopping_time_limit=10*3600)


## 当模型性能突破1.1就停止
exp2 = make_experiment(df_train,
					 target=target,
					 log_level='info',
					 max_trilas=10000, #使用早停策略,总搜索次数可以设置得足够大,默认为10
					 early_stopping_reward=1.1)


## 当搜索连续50次性能都没有提升
exp3 = make_experiment(df_train,
					 target=target,
					 log_level='info',
					 max_trilas=10000, #使用早停策略,总搜索次数可以设置得足够大,默认为10
					 early_stopping_rounds=50)
estiamtor = exp2.run()



##模型评估
scorer=get_scorer('neg_log_loss')
score = scorer(estimator,df_test,df_test[target])
score 

附2:

同样的你在使用hypergbm进行建模的时候,可以设置n_estimators较大,然后使用单模型的早停策略即可。代码如下:

from hypergbm.search_space import GeneralSearchSpaceGenerator
search_space_ = GeneralSearchSpaceGenerator(n_estimators= 900##默认值为200
exp4 = make_experiment(df_train,
					 target=target,
					 log_level='info',
					 max_trilas=100, 
					 search_space=search_space_,
					 estimator_early_stopping_rounds = 100#默认值为n_estimators//20
					 )
estiamtor = exp4.run()
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值