一、模型调参思路
第一步是要找准目标,这个目标是提升某个模型评估指标。
第二步考虑模型在未知数据上的准确率受什么因素影响。
二、泛化误差
1、当模型在未知数据(测试集或者袋外数据)上表现糟糕时,我们说模型的泛化程度不够,泛化误差大。
2、模型复杂度与泛化误差关系
当模型太复杂,模型就会过拟合,泛化能力就不够,所以泛化误差大。当模型太简单,模型就会欠拟合,拟合能力就不够,所以误差也会大。
3、结论
- 模型太复杂或者太简单,都会让泛化误差高,我们追求的是位于中间的平衡点
- 模型太复杂就会过拟合,模型太简单就会欠拟合
- 对树模型和树的集成模型来说,树的深度越深,枝叶越多,模型越复杂
- 树模型和树的集成模型的目标,都是减少模型复杂度,把模型往图像的左边移动
树模型需要降低模型复杂度!
4、参数对于模型性能影响
参数 | 对模型在未知数据上评估性能的影响 | 影响程度 |
---|---|---|
n_estimators | 提升至平稳,n_estimators↑,不影响单个模型的复杂度 | ⭐⭐⭐⭐ |
max_depth | 有增有减,默认最大深度,即最高复杂度,向复杂度降低的方向调参max_depth↓,模型更简单,且向图像的左边移动 | ⭐⭐⭐ |
min_samples_leaf | 有增有减,默认最小限制1,即最高复杂度,向复杂度降低的方向调参min_samples_leaf↑,模型更简单,且向图像的左边移动 | ⭐⭐ |
min_samples_split | 有增有减,默认最小限制2,即最高复杂度,向复杂度降低的方向调参min_samples_split↑,模型更简单,且向图像的左边移动 | ⭐⭐ |
max_features | 有增有减,默认auto,是特征总数的开平方,位于中间复杂度,既可以向复杂度升高的方向,也可以向复杂度降低的方向调参,max_features↓,模型更简单,图像左移;max_features↑,模型更复杂,图像右移;max_features是唯一的,既能够让模型更简单,也能够让模型更复杂的参数,所以在调整这个参数的时候,需要考虑我们调参的方向 | ⭐ |
criterion | 一般适用gini | 具体情况,具体分析 |
三、随机森林在乳腺癌上的调参
乳腺癌数据是sklearn自带的分类数据之一。
1、导入模块
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
2、查看数据特征与目标
data=load_breast_cancer()
data
data.target
data.data
data.data.shape
3、进行简单建模
#简单建模
rfc=RandomForestClassifier(n_estimators=100,random_state=90)
score_pre=cross_val_score(rfc,data.data,data.target,cv=10).mean()
print(score_pre)
输出结果:
4、绘制n_estimators学习曲线
score1=[]
for i in range(0,200,10):
rfc=RandomForestClassifier(n_estimators=i+1
,n_jobs=-1
,random_state=90
)
score=cross_val_score(rfc,data.data,data.target,cv=10).mean()
score1.append(score)
print(max(score1),(score1.index(max(score1))*10)+1)
plt.figure(figsize=[20,5])
plt.plot(range(1,201,10),score1)
plt.show()
输出结果:
因此,当n_estimators=71时,准确率最高位0.9631.
然后,我们进一步细化n_estimators的学习曲线。
scorel=[]
for i in range(65,75):
rfc=RandomForestClassifier(n_estimators=i
,n_jobs=-1
,random_state=90
)
score=cross_val_score(rfc,data.data,data.target,cv=10).mean()
scorel.append(score)
print((max(scorel)),([*range(65,75)][scorel.index(max(scorel))]))
plt.figure(figsize=[20,5])
plt.plot(range(65,75),scorel)
plt.show()
输出结果:
0.9666353383458647,73
5、通过网格调整max_depth参数
#调整max_depth
param_grid={'max_depth':np.arange(1,20,1)}
# 一般根据数据的大小来进行一个试探,乳腺癌数据很小,所以可以采用1~10,或者1~20这样的试探
# 但对于像digit recognition那样的大型数据来说,我们应该尝试30~50层深度(或许还不足够
# 更应该画出学习曲线,来观察深度对模型的影响
rfc=RandomForestClassifier(n_estimators=73
,random_state=90
,n_jobs=-1
)
GS=GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_)
输出结果:
max_depth进行改变,准确率没有改变。
6、调整max_features
param_grid={'max_features':np.arange(5,30,1)}
rfc=RandomForestClassifier(n_estimators=73
,random_state=90
,n_jobs=-1
)
GS=GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_)
输出结果:
当max_features=24时,模型准确率提升。
同理进行其他参数的调整。
最后得到最佳参数:
rfc=RandomForestClassifier(n_estimators=73
,max_features=24
,n_jobs=-1
,random_state=90
)
score=cross_val_score(rfc,data.data,data.target,cv=10).mean()
print(score)
输出结果:
0.9666666666666668