随机森林在乳腺癌数据上的调参
理论:
在机器学习中,我们用来衡量模型在未知数据上的准确率的指标,叫做泛化误差。当模型在未知数据上表现糟糕时,说明模型的泛化程度不够,泛化误差大,模型的效果不好。泛化误差受到模型的结构(复杂度)的影响。当模型太复杂,模型会过拟合,泛化误差大。当模型太简单,模型就会欠拟合,泛化误差也会大。
调参的过程:判断模型处于图像的哪一边,然后减少或者增加模型的复杂度,把模型往图像的左边或者右边移动,到最佳模型复杂度,泛化误差最低点。
对于随机森林:
- 模型太复杂或者太简单,都会让泛化误差高,我们追求的是中间的平衡点。
- 模型太复杂就会过拟合,模型太简单就会欠拟合。
- 对树模型和树的集成模型来说, 树的深度越深,枝叶越多,模型越复杂。
- 树模型和树的集成模型的目标,基本上都是减少模型的复杂度,把模型往图像的左边移动。
实践:
1、先导包,sklearn的模块,乳腺癌数据集
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()
rfc = RandomForestClassifier(n_estimators = 100, random_state = 90)
score_pre = cross_val_score(rfc, data.data, data.target, cv = 10).mean()
结果:score_pre 0.9648809523809524
3、开始调参,先学习曲线再网格搜索
'''
首先用学习曲线
也可以使用网格搜索,但是只有学习曲线能看见趋势
要看见n_estimators在什么取值变得平稳,是否一直推动模型整体准确率的上升等信息
第一次的学习曲线可以用来帮助我们划定范围,取每10个数作为一个阶段,来观察n_estiamtors的变化如何引起模型整体准确率的变化
'''
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) # score1是列表,list.index([objext]) 表示返回object在list中的索引
#上面这一步就是打印出最大的分数,以及对应最大分数的n_estimators取值
plt.figure(figsize=[20,5])
plt.plot(range(1,201,10), score1)
plt.show()
'''
确定好范围后,再进一步细化学习曲线
峰值锁定在35-75之间
'''
score1 = []
for i in range(35, 75):
rfc = RandomForestClassifier(n_estimators = i
,n_jobs = -1
,random_state = 90)
score = cross_val_score(rfc, data.data, data.target, cv = 10).mean()
score1.append(score)
print(max(score1),([*range(35,75)][score1.index(max(score1))])) # score1是列表,list.index([objext]) 表示返回object在list中的索引
#上面这一步就是打印出最大的分数,以及对应最大分数的n_estimators取值
plt.figure(figsize=[20,5])
plt.plot(range(35,75), score1)
plt.show()
n_estimators=73时效果最好。
调整n_estimators的效果显著,模型的准确率立刻上升了,达到0.9666。
接下来进入网格搜索,我们将使用网格搜索对参数一个个进行调整。
为什么不同时调整多个参数?
- 同时调整多个参数会运行缓慢
- 同时调整多个参数,会让我们无法理解参数得到组合是怎么得到的,所以即便网格搜索调出来的结果不好,我们也不知道如何去改,也是为了便于使用复杂度-泛化误差方法(方差-偏差方法)。
'''
网格搜索
有一些参数是没有参照的,很难说清范围,这种情况下我们使用学习曲线,看趋势从曲线中跑出的结果中选取一个更小的区间,再跑曲线
有一些参数可以找到一个范围,或者说我们知道他们的取值和随着他们的取值,模型的整体准确率变化,这样的参数我们就直接跑网格搜索
'''
#开始按照参数对模型整体准确率的影响程度进行调参,首先调整max_depth
#一般根据数据的大小进行一个试探,乳腺癌数据很小,所以可以采用1-10,或者1-20
#但对于像digit recognition大型数据来说,应该尝试30-50层深度(或者更大)
#最好画出学习曲线,来观察深度对模型的影响
param_grid = {'max_depth': np.arange(1, 20, 1)}
rfc = RandomForestClassifier(n_estimators = 73
,random_state = 90
)
GS = GridSearchCV(rfc, param_grid, cv = 10)
GS.fit(data.data, data.target)
GS.best_params_ #显示调整出来的最佳参数 {'max_depth': 8}
GS.best_score_ #显示调整好的最佳参数对应准确率 0.9666353383458647
效果没有变化,再继续调整max_features:
#调整max_features (最大特征数开平方,最大特征数)
param_grid = {'max_features': np.arange(5, 30, 1)}
rfc = RandomForestClassifier(n_estimators = 73
,random_state = 90
)
GS = GridSearchCV(rfc, param_grid, cv = 10)
GS.fit(data.data, data.target)
GS.best_params_ #显示调整出来的最佳参数 {'max_features': 24}
GS.best_score_ #显示调整好的最佳参数对应准确率 0.9666666666666668
准确度提高了一点点,把max_features设置为24.
可以继续调整min_samples_leaf和min_samples_split,但是对照误差与复杂度的图像,模型应该在图像的左边了,这俩个参数用来减小复杂度的,理论上不需要调整了。在此尝试一下看看:
#调整min_samples_leaf
#对于min_samples_leaf和min_samples_split一般是从他们的最小值开始向上增加10或20
#面对高维度的样本量数据,可以直接+50,对于大型数据,可能需要200-300的范围
#如果调整的时候发现准确率无论如何都上不来,可以大胆调一个很大的数据,大力限制模型的复杂度
param_grid = {'min_samples_leaf': np.arange(1, 1+10, 1)}
rfc = RandomForestClassifier(n_estimators = 73
,random_state = 90
)
GS = GridSearchCV(rfc, param_grid, cv = 10)
GS.fit(data.data, data.target)
GS.best_params_ #显示调整出来的最佳参数 {'min_samples_leaf': 1}
GS.best_score_ #显示调整好的最佳参数对应准确率 0.9666353383458647
没有效果。
最后再尝试调节criterion,这个对复杂度的影响未知。
#最后尝试调节criterion
param_grid = {'criterion':['gini','entropy']}
rfc = RandomForestClassifier(n_estimators = 73
,random_state = 90
)
GS = GridSearchCV(rfc, param_grid, cv = 10)
GS.fit(data.data, data.target)
GS.best_params_ #显示调整出来的最佳参数 {'criterion': 'gini'}
GS.best_score_ #显示调整好的最佳参数对应准确率 0.9666353383458647