机器学习中,我们用来衡量模型在未知数据上的准确率的指标,叫做泛化误差(Genelization error)。
那模型的复杂度与我们的参数有什么关系呢?对树模型来说,树越茂盛,深度越深,枝叶越多,模型就越复杂。所以树模型是天生位于图的右上角的模型,随机森林是以树模型为基础,所以随机森林也是天生复杂度高的模型。随机森林的参数,都是向着一个目标去:减少模型的复杂度,把模型往图像的左边移动,防止过拟合。当然了,调参没有绝对,也有天生处于图像左边的随机森林,所以调参之前,我们要先判断,模型现在究竟处。我们只需要记住这四点:
1)模型太复杂或者太简单,都会让泛化误差高,我们追求的是位于中间的平衡点
2)模型太复杂就会过拟合,模型太简单就会欠拟合
3)对树模型和树的集成模型来说,树的深度越深,枝叶越多,模型越复杂
4)树模型和树的集成模型的目标,都是减少模型复杂度,把模型往图像的左边移动
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
data=load_breast_cancer()
#进行一次简单的建模,看看模型本身在数据集上的效果
rfc = RandomForestClassifier(n_estimators=100,random_state=90)
score_pre = cross_val_score(rfc,data.data,data.target,cv=10).mean()
#print(score_pre)
#随机森林调整的第一步:无论如何先来调n_estimators
scorel = []
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()
scorel.append(score)
print(max(scorel),(scorel.index(max(scorel))*10)+1)
#list.index([object])
#返回这个object在列表list中的索引
plt.figure(figsize=[20,5])
plt.plot(range(1,201,10),score1)
#print(plt.show)
# 在确定好的范围内,进一步细化曲线
scorel = []
for i in range(35,45):
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(35,45)][scorel.index(max(scorel))]))
plt.figure(figsize=[20,5])
plt.plot(range(35,45),scorel)
#print(plt.show())
#网格搜索
#调整max_depth
param_grid={'max_depth':np.arange(1,20,1)}
rfc = RandomForestClassifier(n_estimators=39
,random_state=90
)
GS=GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_ )#显示调整出来的最佳参数
print(GS.best_score_) #返回调整好的最佳参数的对应的准确率
在这里,我们注意到,将max_depth设置为有限之后,模型的准确率下降了。限制max_depth,是让模型变得简单,把模型向左推,而模型整体的准确率下降了,即整体的泛化误差上升了,这说明模型现在位于图像左边,即泛化误差最低点的左边(偏差为主导的一边)。通常来说,随机森林应该在泛化误差最低点的右边,树模型应该倾向于过拟合,而不是拟合不足。这和数据集本身有关,但也有可能是我们调整的n_estimators对于数据集来说太大,因此将模型拉到泛化误差最低点去了。然而,既然我们追求最低泛化误差,那我们就保留这个n_estimators,除非有其他的因素,可以帮助我们达到更高的准确率。当模型位于图像左边时,我们需要的是增加模型复杂度(增加方差,减少偏差)的选项,因此max_depth应该尽量大,min_samples_leaf和min_samples_split都应该尽量小。这几乎是在说明,除了max_features,我们没有任何参数可以调整了,因为max_depth,min_samples_leaf和min_samples_split是剪枝参数,是减小复杂度的参数。
在这里,我们可以预言,我们已经非常接近模型的上限,模型很可能没有办法再进步了。
调整max_features:
#调整max_features
param_grid = {'max_features':np.arange(5,30,1)}
"""
max_features是唯一一个即能够将模型往左(低方差高偏差)推,也能够将模型往右(高方差低偏差)推的参数。我
们需要根据调参前,模型所在的位置(在泛化误差最低点的左边还是右边)来决定我们要将max_features往哪边调。
现在模型位于图像左侧,我们需要的是更高的复杂度,因此我们应该把max_features往更大的方向调整,可用的特征
越多,模型才会越复杂。max_features的默认最小值是sqrt(n_features),因此我们使用这个值作为调参范围的
最小值。
"""
rfc = RandomForestClassifier(n_estimators=39
,random_state=90
)
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_)
模型的准确率降低
调整:min_samples_leaf和min_samples_split,
和上述相同的部分不写了
param_grid={'min_samples_leaf':np.arange(1, 1+10, 1)}
param_grid={'min_samples_split':np.arange(2, 2+20, 1)}
#对于min_samples_split和min_samples_leaf,一般是从他们的最小值开始向上增加10或20
与理论一样模型整体的准确率降低了
#调整Criterion
param_grid = {'criterion':['gini', 'entropy']}
rfc = RandomForestClassifier(n_estimators=39
,random_state=90
)
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_)
模型的准确率降低
所以最佳参数就是n_estimators
rfc = RandomForestClassifier(n_estimators=39,random_state=90)
score = cross_val_score(rfc,data.data,data.target,cv=10).mean()
来源于菜菜教程