机器学习之随机森林(sklearn)

2023-05-16

文章目录

  • 1. 概述
    • 1.1 集成算法的概述
    • 1.2 sklearn中的集成算法
  • 2. RandomForestClassfier
    • 2.1 重要参数
      • 2.1.1 控制基评估器的参数
      • 2.1.2 n_estimators
      • 2.1.3 random_state
      • 2.1.4 bootstrap & oob_score
    • 2.2 重要属性接口
  • 3. RandomForestRegressor
  • 4. 调参
  • 5. 在乳腺癌数据集上进行调参
  • 6. 附录
    • 6.1 Bagging vs Boosting
    • 6.2 RFC的参数列表
    • 6.3 RFC的属性列表
    • 6.4 RFC的接口列表

1. 概述

1.1 集成算法的概述

  集成学习(ensemble learning)是时下非常流行的机器学习算法,它本身不是一个单独的机器学习算法,而是通 过在数据上构建多个模型,集成所有模型的建模结果。基本上所有的机器学习领域都可以看到集成学习的身影,在 现实中集成学习也有相当大的作用,它可以用来做市场营销模拟的建模,统计客户来源,保留和流失,也可用来预 测疾病的风险和病患者的易感性。在现在的各种算法竞赛中,随机森林,梯度提升树(GBDT),Xgboost等集成 算法的身影也随处可见,可见其效果之好,应用之广。

集成算法的目标
集成算法会考虑多个评估器的建模结果,汇总之后得到一个综合的结果,以此来获取比单个模型更好的回归或 分类表现

  多个模型集成成为的模型叫做集成评估器(ensemble estimator),组成集成评估器的每个模型都叫做基评估器 (base estimator)。通常来说,有三类集成算法:装袋法(Bagging),提升法(Boosting)和stacking。
在这里插入图片描述
  袋装法核心思想是构建多个相互独立的评估器,然后对其进行平均或者多数表决的原则来决定评估器的结果。最典型的袋装法模型就是随机森林。
  提升法中,基评估器是相关的,是按顺序一一构建的。其核心思想是结合弱评估器的力量一次次对难以评估的样本 进行预测,从而构成一个强评估器。提升法的代表模型有Adaboost和梯度提升树。

1.2 sklearn中的集成算法

  • sklearn中的继承算法模块ensemble
    2.1.1 控制基评估器的参数
参数含义
criterion不纯度的衡量指标,有基尼系数和信息熵两种选择
max_depth树的最大深度,超过最大深度的树枝都会被剪掉
min_samples_leaf一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样 本,否则分枝就不会发生
min_samples_split一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分 枝,否则分枝就不会发生
max_featuresmax_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃, 默认值为总特征个数开平方取整
min_impurity_decrease限制信息增益的大小,信息增益小于设定数值的分枝不会发生

集成算法中,有一半以上都是树的集成模型,可以想见决策树在集成中必定是有很好的效果。

2. RandomForestClassfier

class sklearn.ensemble.RandomForestClassifier (n_estimators=’10’, criterion=’gini’,max_depth=None,min_samples_split=2,min_samples_leaf=1, min_weight_fraction_leaf=0.0,max_features=’auto’,max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0, warm_start=False, class_weight=None)

随机森林是非常具有代表性的Bagging集成算法,它的所有基评估器都是决策树,分类树组成的森林就叫做随机森 林分类器,回归树所集成的森林就叫做随机森林回归器。

2.1 重要参数

2.1.1 控制基评估器的参数

参数含义
criterion不纯度的衡量指标,有基尼系数和信息熵两种选择
max_depth树的最大深度,超过最大深度的树枝都会被剪掉
min_samples_leaf一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样 本,否则分枝就不会发生
min_samples_split一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分 枝,否则分枝就不会发生
max_featuresmax_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃, 默认值为总特征个数开平方取整
min_impurity_decrease限制信息增益的大小,信息增益小于设定数值的分枝不会发生

  具体的可以看另一篇博客《机器学习之决策树》

2.1.2 n_estimators

  这是森林中树木的数量,即基评估器的数量。这个参数对随机森林模型的精确性影响是单调的,n_estimators越大,模型的效果往往越好。但是相应的,任何模型都有决策边界,n_estimators达到一定的程度之后,随机森林的精确性往往不在上升或开始波动,并且,n_estimators越大,需要的计算量和内存也越大,训练的时间也会越来越长。对于这个参数,我们是渴望在训练难度和模型效果之间取得平衡
  n_estimators的默认值在现有版本的sklearn中是10,但是在即将更新的0.22版本中,这个默认值会被修正为 100。这个修正显示出了使用者的调参倾向:要更大的n_estimators

红酒数据案例:

  1. 导入需要的包
%matplotlib inline
from sklearn.tree import DecisionTreeClassifier 
from sklearn.ensemble import RandomForestClassifier 
from sklearn.datasets import load_wine
  1. 导入需要的数据集
wine = load_wine()
#查看红酒数据
wine.data 
wine.target
  1. sklearn的建模基本流程
from sklearn.model_selection import train_test_split
Xtrain, Xtest, Ytrain, Ytest=train_test_split(wine.data,wine.target,test_size=0.3)
clf = DecisionTreeClassifier(random_state=0) 
rfc = RandomForestClassifier(random_state=0) 
clf = clf.fit(Xtrain,Ytrain)
rfc = rfc.fit(Xtrain,Ytrain)
score_c = clf.score(Xtest,Ytest)
score_r = rfc.score(Xtest,Ytest)
print("Single Tree:{}".format(score_c) ,"Random Forest:{}".format(score_r) )
##Single Tree:0.9074074074074074   Random Forest:0.9629629629629629

  1. 画出随机森林和决策树在一组交叉验证下的效果对比
from sklearn.model_selection import cross_val_score 
import matplotlib.pyplot as plt
rfc = RandomForestClassifier(n_estimators=25)
rfc_s = cross_val_score(rfc,wine.data,wine.target,cv=10)
clf = DecisionTreeClassifier()
clf_s = cross_val_score(clf,wine.data,wine.target,cv=10)
plt.plot(range(1,11),rfc_s,label = "RandomForest")
plt.plot(range(1,11),clf_s,label = "Decision Tree") 
plt.legend()
plt.show()

在这里插入图片描述
5. n_estimators的学习曲线

superpa = []
for i in range(200):
	rfc = RandomForestClassifier(n_estimators=i+1,n_jobs=-1)
	rfc_s = cross_val_score(rfc,wine.data,wine.target,cv=10).mean()
	superpa.append(rfc_s)
print(max(superpa),superpa.index(max(superpa))) 
plt.figure(figsize=[20,5])
plt.plot(range(1,201),superpa)
plt.show()

在这里插入图片描述
随机森林使用了集成算法,所以效果一定比单个决策树要好得多。

2.1.3 random_state

  随机森林的本质是一种装袋集成算法(bagging),装袋集成算法是对基评估器的预测结果进行平均或用多数表决 原则来决定集成评估器的结果。在刚才的红酒例子中,我们建立了25棵树,对任何一个样本而言,平均或多数表决 原则下,当且仅当有13棵以上的树判断错误的时候,随机森林才会判断错误。单独一棵决策树对红酒数据集的分类 准确率在0.85上下浮动,假设一棵树判断错误的可能性为0.2(ε),那20棵树以上都判断错误的可能性是:
e r a n d o m f o r e s t = ∑ i = 13 25 C 25 i ϵ i ( 1 − ϵ ) 25 − i = 0.000369 e_{random_forest} = \sum_{i=13}^{25}C_{25}^{i}\epsilon^i(1-\epsilon)^{25-i}=0.000369 erandomforest=i=1325C25iϵi(1ϵ)25i=0.000369
  其中,i是判断错误的次数,也是判错的树的数量,ε是一棵树判断错误的概率,(1-ε)是判断正确的概率,共判对 25-i次。采用组合,是因为25棵树中,有任意i棵都判断错误。

import numpy as np
from scipy.special import comb
np.array([comb(25,i)*(0.2**i)*((1-0.2)**(25-i)) for i in range(13,26)]).sum()
#0.000369

  可见,判断错误的几率非常小,这让随机森林在红酒数据集上的表现远远好于单棵决策树。
  那现在就有一个问题了:我们说袋装法服从多数表决原则或对基分类器结果求平均,这即是说,我们默认森林中的 每棵树应该是不同的,并且会返回不同的结果。设想一下,如果随机森林里所有的树的判断结果都一致(全判断对 或全判断错),那随机森林无论应用何种集成原则来求结果,都应该无法比单棵决策树取得更好的效果才对。但我们使用了一样的类DecisionTreeClassifier,一样的参数,一样的训练集和测试集,为什么随机森林里的众多树会有不同的判断结果?
  sklearn中的分类树DecisionTreeClassifier自带随机性,所以随机森林中的树天生就都是不一样的。决策树从最重要的特征中随机选择出一个特征来进行分枝,因此每次生成的决策树都不一样,这个功能由参数random_state控制。
  随机森林中其实也有random_state,用法和分类树中相似,只不过在分类树中,一个random_state只控制生成一 棵树,而随机森林中的random_state控制的是生成森林的模式,而非让一个森林中只有一棵树。

rfc = RandomForestClassifier(n_estimators=10,random_state=2) 
rfc = rfc.fit(Xtrain, Ytrain)
#随机森林的重要属性之一:estimators,查看森林中树的状况
rfc.estimators_[0].random_state
for i in range(len(rfc.estimators_)):
	print(rfc.estimators_[i].random_state)
'''
1872583848
794921487
111352301
1853453896
213298710
1922988331
1869695442
2081981515
1805465960
'''

  可以观察到,当random_state固定时,随机森林中生成是一组固定的树(多次运行,这组的每棵树的random_state都是一样的。),但每棵树依然是不一致的,这是用随机挑选特征进行分枝的方法得到的随机性。并且我们可以证明,当这种随机性越大的时候,袋装法的效果一 般会越来越好。用袋装法集成时,基分类器应当是相互独立的,是不相同的。
  除了随机挑选特征之外,还要随机挑选样本。这样每个基分类器都具有更大的随机性,集成的效果也会更好。

2.1.4 bootstrap & oob_score

  要让基分类器尽量都不一样,一种很容易理解的方法是使用不同的训练集来进行训练,而袋装法正是通过有放回的 随机抽样技术来形成不同的训练数据,bootstrap就是用来控制抽样技术的参数。
  在一个含有n个样本的原始训练集中,我们进行随机采样,每次采样一个样本,并在抽取下一个样本之前将该样本 放回原始训练集,也就是说下次采样时这个样本依然可能被采集到,这样采集n次,最终得到一个和原始训练集一 样大的,n个样本组成的自助集。由于是随机采样,这样每次的自助集和原始数据集不同,和其他的采样集也是不 同的。这样我们就可以自由创造取之不尽用之不竭,并且互不相同的自助集,用这些自助集来训练我们的基分类 器,基分类器自然也就各不相同了。
bootstrap参数默认True,代表采用这种有放回的随机抽样技术。通常,这个参数不会被我们设置为False。
在这里插入图片描述
  然而有放回抽样也会有自己的问题。由于是有放回,一些样本可能在同一个自助集中出现多次,而其他一些却可能 被忽略,一般来说,自助集大约平均会包含63%的原始数据。因为每一个样本被抽到某个自助集中的概率为:
1 − ( 1 − 1 n ) n = 0.632 1-(1-\frac{1}{n})^{n} = 0.632 1(1n1)n=0.632
  当n足够大时,这个概率收敛于1-(1/e),约等于0.632。因此,会有约37%的训练数据被浪费掉,没有参与建模,
  这些数据被称为袋外数据(out of bag data,简写为oob)。除了我们最开始就划分好的测试集之外,这些数据也可 以被用来作为集成算法的测试集。也就是说,在使用随机森林时,我们可以不划分测试集和训练集,只需要用袋外 数据来测试我们的模型即可。当然,这也不是绝对的,当n和n_estimators都不够大的时候,很可能就没有数据掉落在袋外,自然也就无法使用oob数据来测试模型了。
  如果希望用袋外数据来测试,则需要在实例化时就将oob_score这个参数调整为True,训练完毕之后,我们可以用 随机森林的另一个重要属性:oob_score_来查看我们的在袋外数据上测试的结果:

#无需划分训练集和测试集
rfc = RandomForestClassifier(n_estimators=25,oob_score=True) 
rfc = rfc.fit(wine.data,wine.target)
#重要属性oob_score_ 
rfc.oob_score_
#0.9775280898876404

2.2 重要属性接口

  至此,所有随机森林中的重要参数:n_estimators,random_state,boostrapoob_score这四个参数解释了袋装法的基本流程和重要概念。同时,还了解了**.estimators_ 和 .oob_score_** 这两个重要属性。除了这两个属性之外,作为树模型的集成算法,随机森林自然也有**.feature_importances_**这个属性。
  随机森林的接口与决策树完全一致,因此依然有四个常用接口:apply, fit, predict和score。除此之外,还需要注 意随机森林的predict_proba接口,这个接口返回每个测试样本对应的被分到每一类标签的概率,标签有几个分类 就返回几个概率。如果是二分类问题,则predict_proba返回的数值大于0.5的,被分为1,小于0.5的,被分为0。 传统的随机森林是利用袋装法中的规则,平均或少数服从多数来决定集成的结果,而sklearn中的随机森林是平均每个样本对应的predict_proba返回的概率,得到一个平均概率,从而决定测试样本的分类。

rfc = RandomForestClassifier(n_estimators=25) 
rfc = rfc.fit(Xtrain, Ytrain)
rfc.score(Xtest,Ytest)			#得分
rfc.feature_importances_ 		#属性的重要程度
rfc.apply(Xtest)				#每个样本被分到哪个节点
rfc.predict(Xtest)				#预测属性
rfc.predict_proba(Xtest)		#预测样本是每一类的概率

Bagging的另一个条件是每个基预测器准确率一定要>50%不然集成出来的会很糟糕。

3. RandomForestRegressor

class sklearn.ensemble.RandomForestRegressor (n_estimators=’warn’, criterion=’mse’, max_depth=None,min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=’auto’,max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0, warm_start=False)

所有的参数,属性与接口,全部和随机森林分类器一致。仅有的不同就是回归树与分类树的不同,不纯度的指标, 参数Criterion不一致。
  在决策树中我们已经讲了回归的Criterion。可以看《机器学习之决策树》中的内容。

实例:用随机森林回归填补缺失值

  我们从现实中收集的数据,几乎不可能是完美无缺的,往往都会有一些缺失值。面对缺失值,很多人选择的方式是 直接将含有缺失值的样本删除,这是一种有效的方法,但是有时候填补缺失值会比直接丢弃样本效果更好,即便我 们其实并不知道缺失值的真实样貌。在sklearn中,我们可以使用sklearn.impute.SimpleImputer来轻松地将均值,中值,或者其他最常用的数值填补到数据中,在这个案例中,使用均值,0,和随机森林回归来填补缺 失值,并验证四种状况下的拟合状况,找出对使用的数据集来说最佳的缺失值填补方法。

  1. 导入需要的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import cross_val_score
  1. 以波士顿数据集为例,导入完整的数据集并探索
dataset = load_boston()
dataset.data.shape
#总共506*13=6578个数据
X_full, y_full = dataset.data, dataset.target 
n_samples = X_full.shape[0]		#506个样本
n_features = X_full.shape[1]	#13个特征
  1. 为完整数据集放入缺失值
#首先确定我们希望放入的缺失数据的比例,在这里我们假设是50%,那总共就要有3289个数据缺失
rng = np.random.RandomState(0)
missing_rate = 0.5
n_missing_samples = int(np.floor(n_samples * n_features * missing_rate)) #np.floor向下取整,返回.0格式的浮点数

#所有数据要随机遍布在数据集的各行各列当中,而一个缺失的数据会需要一个行索引和一个列索引
#如果能够创造一个数组,包含3289个分布在0~506中间的行索引,和3289个分布在0~13之间的列索引,那我们就可 以利用索引来为数据中的任意3289个位置赋空值
#然后我们用0,均值和随机森林来填写这些缺失值,然后查看回归的结果如何
missing_features = rng.randint(0,n_features,n_missing_samples) 
missing_samples = rng.randint(0,n_samples,n_missing_samples)

X_missing = X_full.copy() 
y_missing = y_full.copy()

X_missing[missing_samples,missing_features] = np.nan
X_missing = pd.DataFrame(X_missing)
#转换成DataFrame是为了后续方便各种操作,numpy对矩阵的运算速度快到拯救人生,但是在索引等功能上却不如 pandas来得好用

X_missing
0123456789101112
0NaN18.0NaNNaN0.538NaN65.24.09001.0296.0NaNNaN
10.027310.0NaN0.00.469NaN78.94.96712.0NaNNaN396.9
20.02729NaN7.070.0NaN7.18561.1NaN2.0242.0NaNNaN
3NaNNaNNaN0.00.458NaN45.8NaNNaN222.018.7NaN
4NaN0.02.180.0NaN7.147NaNNaNNaNNaN18.7NaN
  1. 使用0和均值填补缺失值
#使用均值进行填补
from sklearn.impute import SimpleImputer

imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean') 
X_missing_mean = imp_mean.fit_transform(X_missing)
#使用0进行填补
imp_0 = SimpleImputer(missing_values=np.nan, strategy="constant",fill_value=0) X_missing_0 = imp_0.fit_transform(X_missing)
  1. 使用随机森林填补缺失值

  任何回归都是从特征矩阵中学习,然后求解连续型标签y的过程,之所以能够实现这个过程,是因为回归算法认为,特征 矩阵和标签之前存在着某种联系。实际上,标签和特征是可以相互转换的,比如说,在一个“用地区,环境,附近学校数 量”预测“房价”的问题中,我们既可以用“地区”,“环境”,“附近学校数量”的数据来预测“房价”,也可以反过来,用“环境”,“附近学校数量”和“房价”来预测“地区”。而回归填补缺失值,正是利用了这种思想。
  对于一个有n个特征的数据来说,其中特征T有缺失值,我们就把特征T当作标签,其他的n-1个特征和原本的标签组成新 的特征矩阵。那对于T来说,它没有缺失的部分,就是我们的Y_test,这部分数据既有标签也有特征,而它缺失的部分,只有特征没有标签,就是我们需要预测的部分。
  特征T不缺失的值对应的其他n-1个特征 + 本来的标签:X_train 特征T不缺失的值:Y_train
  特征T缺失的值对应的其他n-1个特征 + 本来的标签:X_test 特征T缺失的值:未知,我们需要预测的Y_test
  这种做法,对于某一个特征大量缺失,其他特征却很完整的情况,非常适用。
那如果数据中除了特征T之外,其他特征也有缺失值怎么办?
  答案是遍历所有的特征,从缺失最少的开始进行填补(因为填补缺失最少的特征所需要的准确信息最少)。
  填补一个特征时,先将其他特征的缺失值用0代替,每完成一次回归预测,就将预测值放到原本的特征矩阵中,再继续填 补下一个特征。每一次填补完毕,有缺失值的特征会减少一个,所以每次循环后,需要用0来填补的特征就越来越少。
当 进行到最后一个特征时(这个特征应该是所有特征中缺失值最多的),已经没有任何的其他特征需要用0来进行填补了, 而我们已经使用回归为其他特征填补了大量有效信息,可以用来填补缺失最多的特征。
  遍历所有的特征后,数据就完整,不再有缺失值了。

X_missing_reg = X_missing.copy()
sortindex = np.argsort(X_missing_reg.isnull().sum(axis=0)).values	
for i in sortindex:
	#构建我们的新特征矩阵和新标签
	df = X_missing_reg
	fillc = df.iloc[:,i]
	df = pd.concat([df.iloc[:,df.columns != i],pd.DataFrame(y_full)],axis=1)
	#在新特征矩阵中,对含有缺失值的列,进行0的填补
	df_0 =SimpleImputer(missing_values=np.nan,strategy='constant',fill_value=0).fit_transform(df)
	#找出我们的训练集和测试集
	Ytrain = fillc[fillc.notnull()] 
	Ytest = fillc[fillc.isnull()] 
	Xtrain = df_0[Ytrain.index,:] 
	Xtest = df_0[Ytest.index,:]
	#用随机森林来填补缺失值
	rfc = RandomForestRegressor(n_estimators=100) 
	rfc = rfc.fit(Xtrain, Ytrain)
	Ypredict = rfc.predict(Xtest)
	#将填补好的特征返回到我们的原始的特征矩阵中
	X_missing_reg.loc[X_missing_reg.iloc[:,i].isnull(),i] = Ypredict
  1. 对填补好的数据进行建模
X = [X_full,X_missing_mean,X_missing_0,X_missing_reg]
mse = [] 
std = [] 
for x in X:
	estimator = RandomForestRegressor(random_state=0, n_estimators=100)
	scores = cross_val_score(estimator,x,y_full,scoring='neg_mean_squared_error', cv=5).mean()
	mse.append(scores * -1)
#mse:[21.62860460743544, 40.84405476955929, 49.50657028893417, 16.704135159231207]

可见用随机森林填补的数据甚至比原数据的均方误差都要小!

  1. 用所得结果画出条形图
x_labels = ['Full data',
			'Zero Imputation',
			'Mean Imputation',
			'Regressor Imputation'] 
colors = ['r', 'g', 'b', 'orange']
plt.figure(figsize=(12, 6)) 
ax = plt.subplot(111)
for i in np.arange(len(mse)):
 	x.barh(i, mse[i],color=colors[i], alpha=0.6, align='center') 
ax.set_title('Imputation Techniques with Boston Data')
ax.set_xlim(left=np.min(mse) * 0.9,right=np.max(mse) * 1.1)
ax.set_yticks(np.arange(len(mse)))
ax.set_xlabel('MSE')
ax.set_yticklabels(x_labels)
plt.show()

在这里插入图片描述

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看具体情况

偏差和方差的理解

偏差大偏差小
方差大模型不适合这个数据
换模型
过拟合
模型很复杂
对某些数据集预测很准确
对某些数据集预测很糟糕
方差小欠拟合
模型相对简单
预测很稳定
但对所有的数据预测都不太准确
泛化误差小,我们的目标

在这里插入图片描述
  调参的目标是,达到方差和偏差的完美平衡!虽然方差和偏差不能同时达到最小值,但他们组成的泛化误差却 可以有一个最低点,而我们就是要寻找这个最低点。对复杂度大的模型,要降低方差,对相对简单的模型,要降低 偏差。随机森林的基评估器都拥有较低的偏差和较高的方差,因为决策树本身是预测比较”准“,比较容易过拟合的 模型,装袋法本身也要求基分类器的准确率必须要有50%以上。所以以随机森林为代表的装袋法的训练过程旨在降低方差,即降低模型复杂度,所以随机森林参数的默认设定都是假设模型本身在泛化误差最低点的右边。所以随机森林是天生过拟合的模型

5. 在乳腺癌数据集上进行调参

  案例中,往往使用真实数据,为什么要使用sklearn自带的数据呢?因为真实数据在随机森林下的调参过程,往往非常缓慢。真实数据量大,维度高,在使用随机森林之前需要一系列的处理。随机森林在辨别手写数字的数据上有非常好的表现,其调参案例也是非常经典,但是由于数据的维度太高,太过复杂,运行一次完整的网格搜索需要四五个小时。因此选择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
  1. 导入数据集探索数据
data = load_breast_cancer()
data.data.shape
data.target
#可以看到,乳腺癌数据集有569条记录,30个特征,单看维度虽然不算太高,但是样本量非常少。过拟合的情况可能存在。
  1. 简单建模,看看模型本身在数据集上的性能
rfc = RandomForestClassifier(n_estimators=100,random_state=90) 
score_pre= cross_val_score(rfc,data.data,data.target,cv=10).mean()
score_pre
#0.9666925935528475

#这里可以看到,随机森林在乳腺癌数据上的表现本就还不错,在现实数据集上,基本上不可能什么都不调就看到95%以 上的准确率
  1. 调参第一步,首先调n_estimators
"""
在这里我们选择学习曲线,可以使用网格搜索吗?可以,但是只有学习曲线,才能看见趋势
我个人的倾向是,要看见n_estimators在什么取值开始变得平稳,是否一直推动模型整体准确率的上升等信息
第一次的学习曲线,可以先用来帮助我们划定范围,我们取每十个数作为一个阶段,来观察n_estimators的变化如何 引起模型整体准确率的变化
"""
#####【TIME WARNING: 30 seconds】#####
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) 
plt.figure(figsize=[20,5])
plt.plot(range(1,201,10),scorel)
plt.show()
#list.index([object])
#返回这个object在列表list中的索引

在这里插入图片描述

  1. 在确定好的范围内进一步细化学习曲线
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)
plt.show()
#max score  0.971956831734508839

在这里插入图片描述
  调整n_estimators的效果显著,模型的准确率立刻上升了0.5%。接下来就进入网格搜索,我们将使用网格搜索对 参数一个个进行调整。为什么我们不同时调整多个参数呢?原因有两个:
1)同时调整多个参数会运行非常缓慢
2)同时调整多个参数,会让我们无法理解参数的组合是怎么得来的,所以即便网格搜索调出来的结果不好,我们也不知道从哪里去改。在这里对参数进行一个个地调整。

  1. 为网格搜索做准备
"""
有一些参数是没有参照的,很难说清一个范围,这种情况下我们使用学习曲线,看趋势 从曲线跑出的结果中选取一个更小的区间,再跑曲线
param_grid = {'n_estimators':np.arange(0, 200, 10)}
param_grid = {'max_depth':np.arange(1, 20, 1)}
param_grid = {'max_leaf_nodes':np.arange(25,50,1)}
 对于大型数据集,可以尝试从1000来构建,先输入1000,每100个叶子一个区间,再逐渐缩小范围

有一些参数是可以找到一个范围的,或者说我们知道他们的取值和随着他们的取值,模型的整体准确率会如何变化,这 样的参数我们就可以直接跑网格搜索
param_grid = {'criterion':['gini', 'entropy']}
param_grid = {'min_samples_split':np.arange(2, 2+20, 1)}
param_grid = {'min_samples_leaf':np.arange(1, 1+10, 1)}
param_grid = {'max_features':np.arange(5,30,1)}
"""
  1. 开始按照参数对模型整体准确率的影响程度进行调参,首先调整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=39,random_state=90)
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
GS.best_params_					#{'max_depth': 11}
GS.best_score_					#0.9718804920913884

在这里插入图片描述
  在这里,我们注意到,将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是剪枝参数,是减小复杂度的参数。 在这里,我们可以预言,我们已经非常接近模型的上限,模型很可能没有办法再进步了。

  1. 调整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)
GS.best_params_   #{'max_features': 5}
GS.best_score_	  #0.9718804920913884

  网格搜索返回了max_features的最小值(5),可见max_features升高之后,模型的准确率降低了。这说明,我们把模型往右推,模型的泛化误差增加了。前面用max_depth往左推,现在用max_features往右推,泛化误差都增加, 这说明模型本身已经处于泛化误差最低点,已经达到了模型的预测上限,没有参数可以左右的部分了。剩下的那些误差,是噪声决定的,已经没有方差和偏差的可以调了。
  到这一步其实就可以停下了,因为复杂度和泛化误差的关系已经告诉我们,模型不能再进步 了。调参和训练模型都需要很长的时间,明知道模型不能进步了还继续调整,不是一个有效率的做法。如果我们希 望模型更进一步,我们会选择更换算法,或者更换做数据预处理的方式。

  1. 调整min_samples_leaf
#调整min_samples_leaf
param_grid={'min_samples_leaf':np.arange(1, 1+10, 1)}
#对于min_samples_split和min_samples_leaf,一般是从他们的最小值开始向上增加10或20
#面对高维度高样本量数据,如果不放心,也可以直接+50,对于大型数据,可能需要200~300的范围
#如果调整的时候发现准确率无论如何都上不来,那可以放心大胆调一个很大的数据,大力限制模型的复杂度
rfc = RandomForestClassifier(n_estimators=39
 ,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.9718804920913884

  可以看见,网格搜索返回了min_samples_leaf的最小值,并且模型整体的准确率还降低了,这和max_depth的情 况一致,参数把模型向左推,但是模型的泛化误差上升了。在这种情况下,我们显然是不要把这个参数设置起来的,就让它默认就好了。

  1. 不懈努力,继续尝试min_samples_split
#调整min_samples_split
param_grid={'min_samples_split':np.arange(2, 2+20, 1)}
rfc = RandomForestClassifier(n_estimators=39
						    ,random_state=90)
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
GS.best_params_	#{'min_samples_split': 2}
GS.best_score_	#0.9718804920913884
  1. 最后尝试一下criterion
#调整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)
GS.best_params_		#{'criterion': 'gini'}
GS.best_score_		#0.9718804920913884
  1. 总结出模型最佳参数
rfc = RandomForestClassifier(n_estimators=39,random_state=90) 
score = cross_val_score(rfc,data.data,data.target,cv=10).mean()
score
score - score_pre

  在整个调参过程之中,我们首先调整了n_estimators(无论如何都请先走这一步),然后调整max_depth,通过max_depth产生的结果,来判断模型位于复杂度-泛化误差图像的哪一边,从而选择我们应该调整的参数和调参的 方向。如果感到困惑,也可以画很多学习曲线来观察参数会如何影响我们的准确率,选取学习曲线中单调的部分来 放大研究(如同我们对n_estimators做的)。学习曲线的拐点也许就是我们一直在追求的,最佳复杂度对应的泛化 误差最低点(也是方差和偏差的平衡点)。
  也可以直接网格搜索,就是十分耗时间和资源,不如一个个参数调好了再组合来的省资源。

6. 附录

6.1 Bagging vs Boosting

装袋法 Bagging提升法 Boosting
评估器相互独立,同时运行相互关联,按顺序依次构建,后建的模型会在先建模型预 测失败的样本上有更多的权重
抽样数集有放回抽样有放回抽样,但会确认数据的权重,每次抽样都会给容易预测失败的样本更多的权重
决定集成的结果平均或少数服从多数原则加权平均,在训练集上表现更好的模型会有更大的权重
目标降低方差,提高模型 整体的稳定性降低偏差,提高模型整体的精确度
单个评估器存在过拟合问题的时候能够一定程度上解决过拟合问题可能会加剧过拟合问题
单个评估器的效力比较弱的时候不是非常有帮助很可能会提升模型表现
代表算法随机森林梯度提升树,Adaboost

6.2 RFC的参数列表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.3 RFC的属性列表

在这里插入图片描述

6.4 RFC的接口列表

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习之随机森林(sklearn) 的相关文章

  • pip 安装 sklearn or scikit-learn python3

    安装 sklearn 1 安装 numpy scipy matplot pip3 install numpy scipy matplotlib i https pypi tuna tsinghua edu cn simple 2 安装 sk
  • sklearn实现支持向量机

    机器学习入门实验之支持向量机 简单实验 使用sklearn完成 代码如下 注 本文章主要是为方便自己以后复习所学内容而写 并不做详细介绍 支持向量机 这里是线性核 sklearn自带软间隔支持向量机 import pandas as pd
  • 【实战 01】心脏病二分类数据集

    目录 1 获取数据集 2 数据集介绍 3 数据预处理 4 构建随机森林分类模型 5 预测测试集数据 6 构建混淆矩阵 7 计算查全率 召回率 调和平均值 8 ROC曲线 AUC曲线 注 每一章节可以为一个py文件 4 5 6 7写在同一个文
  • 逻辑回归介绍及statsmodels、sklearn实操

    目录 1 逻辑回归简要介绍 2 statsmodels中实现逻辑回归 3 sklearn实现逻辑回归 3 1 基础案例代码 3 2 样本不平衡问题处理 3 3 LogisticRegression模型参数说明 3 4 模型调优方法 1 逻辑
  • 机器学习之SVM

    文章目录 一 SVM基本介绍 二 SVM工作原理 1 线性支持向量机 数据可分 2 软边距支持向量机 数据不可分 三 sklearn实现SVM 注 SVM涉及距离 需要先数据标准化处理 1 线性SVM LinearSVC 构造函数的参数及默
  • sklearn 转换器和预估器

    刚学习sklearn时 没分清转换器的fit 和模型训练的fit 还以为是一个 结果学完了回过头来 才发现这些差异 再此记录一下 一 sklearn 转换器和预估器 转换器 Transformers 定义 转换器是一种可以对数据进行某种转换
  • sklearn中的LogisticRegression

    sklearn中的逻辑回归接口如下 sklearn linear model LogisticRegression penalty l2 dual False tol 0 0001 C 1 0 fit intercept True inte
  • 机器学习——1.Sklearn:特征工程

    目录 scikit learn数据集API介绍 sklearn小数据集 sklearn大数据集 sklearn数据集的使用 数据集的划分 特征工程 特征抽取 特征提取 特征提取API 字典特征提取 文本特征提取 中文文本特征值抽取 停用词
  • joblib嵌套式并行运行方式

    20220811 0 引言 在进行机器学习的相关实验中 当使用sklearn的时候 通常可以通过n jobs 1这个参数实现某些算法的并行化 例如集成学习的方法 或者是参数搜索的函数 通过查看相关的文档 或者直接去看这个代码 可以发现skl
  • 5-2 有监督特征抽取

    文章目录 5 2 有监督特征抽取 基础知识 项目案例 动手练习 5 2 有监督特征抽取 请参考 数据准备和特征工程 中的相关章节 调试如下代码 基础知识 from sklearn datasets import make classific
  • anaconda已经有sklearn,但是pycharm不能导入的解决方法

    问题 D software Anaconda3 Lib site packages文件夹里已经有sklearn这个文件夹 但是pycharm里import时无法识别到 原因 在pycharm里点击文件 gt 设置 gt 项目 gt Pyth
  • 如何使用OpenAI进行embedding句子后,输入新句子比较

    import openai import numpy as np from sklearn metrics pairwise import cosine similarity Set up OpenAI API credentials op
  • python数据分析预处理z-score标准化

    一 z score标准化的python代码 import pandas from pandas import read excel from sklearn import preprocessing dataset read excel p
  • sklearn中的LASSO

    LASSO import numpy as np import matplotlib pyplot as plt np random seed 42 x np random uniform 3 0 3 0 size 100 X x resh
  • 机器学习概述和数据预处理

    概述 机器学习定义 机器学习是一门能够让编程计算机从数据中学习的计算机科学 一个计算机程序在完成任务T之后 获得经验E 其表现效果为P 如果任务T的性能表现 也就是用来衡量的P 随着E增加而增加 那么这样计算机程序就被称为机器学习系统 自我
  • Sklearn GridSearchCV跑SVM很慢或卡死解决办法,SVM线性核函数卡死

    今天跑人工智能SVM实验 想试一下线性核函数 结果卡死了 很久也不出结果 但之前使用高斯核函数是没问题的 历经千辛万苦终于找到了原因 记录一下 希望对后人有帮助 本人只是个做作业的小菜菜 如有不对欢迎指正 参考了以下文章 关于Python
  • 机器学习——无监督学习

    机器学习的分类 一般分为下面几种类别 监督学习 supervised Learning 无监督学习 Unsupervised Learning 强化学习 Reinforcement Learning 增强学习 半监督学习 Semi supe
  • 实战22:文本摘要实战:基于句子相似度矩阵构建图结构实现文本摘要 代码+数据

    任务描述 自动文本摘要 Text Summarization 是指给出一段文本 我们从中提取出要点 然后再形成一个短的概括性的文本 自动的文本摘要是非常具有挑战性的 当我们作为人类总结一篇文章时 我们通常会完整地阅读它以发展我们的理解 然后
  • PCA+SVM手写数字识别 代码参考

    我可以为您提供一些参考 但是最终具体实现还需要您根据自己的需求进行调整 可以参考下面的代码 from sklearn import datasets from sklearn model selection import train tes
  • 4-2 过滤器法

    4 2 过滤器法 请参考 数据准备和特征工程 中的相关章节 调试如下代码 注意 本节内容因为要耗费比较大的内存 在线平台有可能无法支持 可以下载到本地执行 基础知识 from sklearn datasets import load iri

随机推荐

  • 如何实现一个高性能可渲染大数据的Tree组件

    作者 xff1a jayzou https segmentfault com a 1190000021228976 背景 项目中需要渲染一个5000 43 节点的树组件 xff0c 但是在引入element Tree组件之后发现性能非常差
  • 白剽,2020年最牛AI技术,各个都有代码

    来源 xff1a Reddit 编辑 xff1a 科雨 2020年 xff0c 想必各国的人民都被新冠病毒支配得瑟瑟发抖 不过 xff0c 这并不影响科研工作者的工作态度和产出质量 疫情之下 xff0c 通过各种方式 xff0c 全球的研究
  • 图解:卷积神经网络数学原理解析

    原标题 Gentle Dive into Math Behind Convolutional Neural Networks 作 者 Piotr Skalski 编 辑 Pita 翻 译 通夜 xff08 中山大学 xff09 had in
  • 【第二弹】这可能是进达摩院最好的机会了!

    很长时间没有更新公众号了 xff0c 最近在准备一些其他节目 xff0c 和小伙伴们说声抱歉了 但是 xff0c 虽然近期没有文章 xff0c 福利是不能少的 早在半年前 xff0c 我发过一篇文章 xff1a 这可能是进达摩院最好的机会了
  • Hadoop入门-WordCount示例

    WordCount的过程如图 xff0c 这里记录下入门的过程 xff0c 虽然有很多地方理解的只是皮毛 Hadoop的安装 安装比较简单 xff0c 安装完成后进行单机环境的配置 hadoop env sh 指定JAVA HOME spa
  • Phaser入门教程

    入门教程 xff0c 我可不会讲什么概念 xff0c 我只会讲一个入门例子 xff0c 通过这个例子 xff0c 你就知道 phaser有多么强大 xff0c 而照着这个例子做 xff0c 你就能知道怎么使用 phaser了 需要说明的是
  • IDEA插件activiti工具actiBPM

    最新的IDEA中Marketplace搜索不到actiBPM xff08 2020 2 xff09 离线安装 下载https plugins jetbrains com 选择版本 导入jar 重启IDEA 验证 右键新建 表明添加成功 使用
  • 【内推找我】阿里社招面试16轮,终于拿到offer(2020年2月更新)

    内推私信我 xff0c 标题党了 xff0c 其实是这么回事 一 背景及原因 个人背景 xff1a 17年普本毕业Java开发 想换工作原因 xff1a 19年7月公司裁员了一波 xff0c 内部较动荡 xff0c 想看看外面机会 xff1
  • MPU6050介绍及姿态解算

    1 介绍 xff1a MPU6050 是 InvenSense 公司推出的全球首款整合性 6 轴运动处理组件 xff0c 相较于多组件方案 xff0c 免除了组合陀螺仪与加速器时之轴间差的问题 xff0c 减少了安装空间 xff08 1 x
  • 网络编程——Socket(套接字)

    网络编程 网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯 网络编程中 有两个主要的问题 xff0c 一个是如何准确的定位网络上一台或多台主机 xff0c 另一个就是找到主机后 如何可靠高效的进行数据传输 在TCP IP协议
  • 【Linux 驱动】netfilter/iptables (三) 注册和注销Netfilter hook

    继前面介绍了 netfilter hook xff0c 这里我们开始进行简单的实例讲解 xff0c 主要是Netfilter hook的注册与注销 xff1a wqlkp c xff1a span class hljs preprocess
  • Uboot网络设备驱动(一)---两种连接架构

    本系列将针对NXP的s32v234芯片及s32v234evb开发板讲解Uboot中网络相关的设备驱动程序 本文前提是你有基本的计算机网络知识 xff08 TCP IP协议及OSI ISO七层网络协议 xff09 一般BSP工程师涉及的主要工
  • ESP8266物联网远距离控制实现

    ESP8266物联网远距离控制实现 转载请注明出处 xff01 重要的事情放在前面源码在GitHub上面欢迎issue xff0c 如果可以的话Star一下也是表示对作者的支持 有很多不足 xff0c 希望可以得到指教 https gith
  • JACK报错(Ensure Jack server is installed and started)&多用户编译

    目录 报错内容 报错原因 解决方法 备注 报错内容 20 4823 23656 Ensure Jack server is installed and started FAILED bin bash c 34 prebuilts sdk t
  • linux常用命令

    linux常用命令 pwd 查看当前工作目录的绝对路径 cat input txt 查看input txt文件的内容 cat v input txt 查看input txt文件的编码格式 sed
  • UML中类的关系:关联关系、聚合关系、依赖关系、泛化关系、实现关系

    一 关联关系 关联关系是一种结构化的关系 xff0c 指一种对象和另一种对象有联系 给定关联的两个类 xff0c 可以从其中的一个类的对象访问到另一个类的相关对象 在UML图中 xff0c 关联关系用一条实线表示 另外 xff0c 关联可以
  • 互补滤波

    互补滤波 加速度计对小车的加速度比较敏感 xff0c 取瞬时值计算倾角误差比较大 xff1b 而陀螺仪积分得到的角度不受小车加速度的影响 xff0c 但是随着时间的增加积分漂移和温度漂移带来的误差比较大 所以这两个传感器正好可以弥补相互的缺
  • Linux 网络通讯 : smbclient 命令详解

    smbclient命令属于samba套件 xff0c 它提供一种命令行使用交互式方式访问samba服务器的共享资源 语法 smbclient 选项 参数 选项 B lt ip地址 gt xff1a 传送广播数据包时所用的IP地址 xff1b
  • 云计算的三种部署模式:公有云、私有云、混合云

    随着云时代的到来 xff0c 慢慢的演化出了更有针对性的产品服务 xff0c 公有云 xff0c 私有云 xff0c 混合云 那么这三者之间有什么区别呢 xff1f 我们用打比方的方式来说明 例如我们来到一个城市需要睡觉 xff0c 就要去
  • 机器学习之随机森林(sklearn)

    文章目录 1 概述1 1 集成算法的概述1 2 sklearn中的集成算法 2 RandomForestClassfier2 1 重要参数2 1 1 控制基评估器的参数2 1 2 n estimators2 1 3 random state