目录
三.RandomForestClassifier(随机森林分类器)
七.RandomForestRegressor(随机森林回归器)
一.集成算法
集成学习(ensemble learning)是时下非常流行的机器学习算法,它本身不是一个单独的机器学习算法,而是通过在数据上构建多个模型,集成所有模型的建模结果。集成算法会考虑多个评估器的建模结果,汇总之后得到一个综合的结果,以此来获取比单个模型更好的回归或分类表现。
多个模型集成成为的模型叫做集成评估器(ensemble estimator),组成集成评估器的每个模型都叫做基评估器(base estimator)。通常来说,有三类集成算法:装袋法(Bagging),提升法(Boosting)和stacking。
装袋法的核心思想是构建多个相互独立的评估器,然后对其预测进行平均或多数表决原则来决定集成评估器的结果。装袋法的代表模型就是随机森林。
提升法中,基评估器是相关的,是按顺序一一构建的。其核心思想是结合弱评估器的力量一次次对难以评估的样本进行预测,从而构成一个强评估器。提升法的代表模型有Adaboost和梯度提升树。
二.sklearn中的集成算法模块ensemble
ensemble.AdaBoostClassifier AdaBoost分类
ensemble.AdaBoostRegressor Adaboost回归
ensemble.BaggingClassifier 装袋分类器
ensemble.BaggingRegressor 装袋回归器
ensemble.ExtraTreesClassifier Extra-trees分类(超树,极端随机树)
ensemble.ExtraTreesRegressor Extra-trees回归
ensemble.GradientBoostingClassifier 梯度提升分类
ensemble.GradientBoostingRegressor 梯度提升回归
ensemble.IsolationForest 隔离森林
ensemble.RandomForestClassifier 随机森林分类
ensemble.RandomForestRegressor 随机森林回归
ensemble.RandomTreesEmbedding 完全随机树的集成
ensemble.VotingClassifier 用于不合适估算器的软投票/多数规则分类器
集成算法中,有一半以上都是树的集成模型,可以想见决策树在集成中必定是有很好的效果。
三.RandomForestClassifier(随机森林分类器)
随机森林是非常具有代表性的Bagging集成算法,它的所有基评估器都是决策树,分类树组成的森林就叫做随机森林分类器,回归树所集成的森林就叫做随机森林回归器。
四.重要参数
1.基评估器参数
criterion 不纯度的衡量指标,有基尼系数和信息熵两种选择
max_depth 树的最大深度,超过最大深度的树枝都会被剪掉
min_samples_leaf
一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生
min_samples_split
一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生
max_features
max_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃,默认值为总特征个数开平方取整
min_impurity_decrease 限制信息增益的大小,信息增益小于设定数值的分枝不会发生
2.随机森林参数
n_estimators
这是森林中树木的数量,即基评估器的数量。这个参数对随机森林模型的精确性影响是单调的,n_estimators越大,模型的效果往往越好。但是相应的,任何模型都有决策边界,n_estimators达到一定的程度之后,随机森林的精确性往往不在上升或开始波动,并且,n_estimators越大,需要的计算量和内存也越大,训练的时间也会越来越长。对于这个参数,我们是渴望在训练难度和模型效果之间取得平衡。
random_state
随机森林的本质是一种装袋集成算法(bagging),装袋集成算法是对基评估器的预测结果进行平均或用多数表决原则来决定集成评估器的结果。若建立了25棵树,对任何一个样本而言,平均或多数表决原则下,当且仅当有13棵以上的树判断错误的时候,随机森林才会判断错误。可见,判断错误的几率非常小,这让随机森林的表现远远好于单棵决策树。
随机森林中的random_state,用法和分类树中相似,只不过在分类树中,一个random_state只控制生成一棵树,而随机森林中的random_state控制的是生成森林的模式,而非让一个森林中只有一棵树。
我们可以观察到,当random_state固定时,随机森林中生成是一组固定的树,但每棵树依然是不一致的,用袋装法集成时,基分类器应当是相互独立的,是不相同的。
bootstrap & oob_score
要让基分类器尽量都不一样,一种很容易理解的方法是使用不同的训练集来进行训练,而袋装法正是通过有放回的随机抽样技术来形成不同的训练数据,bootstrap就是用来控制抽样技术的参数。
bootstrap参数默认True,代表采用这种有放回的随机抽样技术。通常,这个参数不会被我们设置为False。
然而有放回抽样也会有自己的问题。由于是有放回,一些样本可能在同一个自助集中出现多次,而其他一些却可能被忽略,一般来说,自助集大约平均会包含63%的原始数据。因为每一个样本被抽到某个自助集中的概率为:
当n足够大时,这个概率收敛于1-(1/e),约等于0.632。因此,会有约37%的训练数据被浪费掉,没有参与建模,这些数据被称为袋外数据(out of bag data,简写为oob)。除了我们最开始就划分好的测试集之外,这些数据也可以被用来作为集成算法的测试集。也就是说,在使用随机森林时,我们可以不划分测试集和训练集,只需要用袋外
数据来测试我们的模型即可。当然,这也不是绝对的,当n和n_estimators都不够大的时候,很可能就没有数据掉落在袋外,自然也就无法使用oob数据来测试模型了。
如果希望用袋外数据来测试,则需要在实例化时就将oob_score这个参数调整为True,训练完毕之后,我们可以用随机森林的另一个重要属性:oob_score_来查看我们的在袋外数据上测试的结果.
五.重要属性和接口
决策树的参数中,通过n_estimators,random_state,boostrap和oob_score这四个参数可以了解袋装法的基本流程和重要概念。同时,还有.estimators_ 和 .oob_score_ 这两个重要属性。除了这两个属性之外,作为树模型的集成算法,随机森林自然也有.feature_importances_这个属性。
随机森林的接口与决策树完全一致,因此依然有四个常用接口:apply(返回每个测试样本所在的叶子节点的索引), fit, predict和score。除此之外,还需要注意随机森林的predict_proba接口,这个接口返回每个测试样本对应的被分到每一类标签的概率,标签有几个分类就返回几个概率。如果是二分类问题,则predict_proba返回的数值大于0.5的,被分为1,小于0.5的,被分为0。传统的随机森林是利用袋装法中的规则,平均或少数服从多数来决定集成的结果,而sklearn中的随机森林是平均每个样本对应的predict_proba返回的概率,得到一个平均概率,从而决定测试样本的分类。
六.Bagging的另一个必要条件
当基分类器的误差率小于0.5,即准确率大于0.5时,集成的效果是比基分类器要好的。相反,当基分类器的误差率大于0.5,袋装的集成算法就失效了。所以在使用随机森林之前,一定要检查,用来组成随机森林的分类树们是否都有至少50%的预测正确率。
七.RandomForestRegressor(随机森林回归器)
所有的参数,属性与接口,全部和随机森林分类器一致。仅有的不同就是回归树与分类树的不同,不纯度的指标,参数Criterion不一致。
值得一提的是,随机森林回归并没有predict_proba这个接口,因为对于回归来说,并不存在一个样本要被分到某个类别的概率问题,因此没有predict_proba这个接口。
回归树衡量分枝质量的指标,支持的标准有三种:
1)输入"mse"使用均方误差mean squared error(MSE),父节点和叶子节点之间的均方误差的差额将被用来作为特征选择的标准,这种方法通过使用叶子节点的均值来最小化L2损失
2)输入“friedman_mse”使用费尔德曼均方误差,这种指标使用弗里德曼针对潜在分枝中的问题改进后的均方误差
3)输入"mae"使用绝对平均误差MAE(mean absolute error),这种指标使用叶节点的中值来最小化L1损失
在使用交叉验证,或者其他方式获取回归树的结果时,我们往往选择均方误差作为我们的评估(在分类树中这个指标是score代表的预测准确率)。在回归中,我们追求的是,MSE越小越好。然而,回归树的接口score返回的是R平方,并不是MSE。虽然均方误差永远为正,但是sklearn当中使用均方误差作为评判标准时,却是计算”负均方误差“(neg_mean_squared_error)。
在交叉验证时,如果不填写scoring = "neg_mean_squared_error",交叉验证默认的模型衡量指标是R平方,因此交叉验证的结果可能有正也可能有负。而如果写上scoring,则衡量标准是负MSE,交叉验证的结果只可能为负。
八.机器学习中调参的基本思想
通过画学习曲线,或者网格搜索,我们能够探索到调参边缘(代价可能是训练一次模型要跑三天三夜),但是在现实中,高手调参恐怕还是多依赖于经验,而这些经验,来源于:1)非常正确的调参思路和方法,2)对模型评估指标的理解,3)对数据的感觉和经验,4)用洪荒之力去不断地尝试。
在机器学习中,我们用来衡量模型在未知数据上的准确率的指标,叫做泛化误差(Genelization error)。
泛化误差
当模型在未知数据(测试集或者袋外数据)上表现糟糕时,我们说模型的泛化程度不够,泛化误差大,模型的效果不好。泛化误差受到模型的结构(复杂度)影响。看下面这张图,它准确地描绘了泛化误差与模型复杂度的关系,当模型太复杂,模型就会过拟合,泛化能力就不够,所以泛化误差大。当模型太简单,模型就会欠拟合,拟合能力就不够,所以误差也会大。只有当模型的复杂度刚刚好的才能够达到泛化误差最小的目标。
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 看具体情况
九.Bagging vs Boosting
十.随机森林代码实现
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
wine=load_wine()
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)
,"\n"
,"Random Forest:{}".format(score_r)
)
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()
# superpa = []
# for i in range(200):
# rfc = RandomForestClassifier(n_estimators=i+1,n_jobs=-1)#在不同的n_estimators下跑
# rfc_s = cross_val_score(rfc,wine.data,wine.target,cv=10).mean()#交叉验证的结果平均值
# superpa.append(rfc_s)
#
# print(max(superpa),superpa.index(max(superpa))+1)#打印出:最高精确度取值,max(superpa))+1指的是森林数目的数量n_estimators;list.index(object)会返回对象object在列表list当中的索引
# plt.figure(figsize=[20,5])
# plt.plot(range(1,201),superpa)
# plt.show()
# rfc_l = []
# clf_l = []
# for i in range(10):
# rfc = RandomForestClassifier(n_estimators=25)#s随机森林的效果比决策树压倒性的强
# rfc_s = cross_val_score(rfc, wine.data, wine.target, cv=10).mean()
# rfc_l.append(rfc_s)
#
# clf = DecisionTreeClassifier()
# clf_s = cross_val_score(clf, wine.data, wine.target, cv=10).mean()
# clf_l.append(clf_s)
#
# plt.plot(range(1, 11), rfc_l, label="Random Forest")
# plt.plot(range(1, 11), clf_l, label="Decision Tree")
# plt.legend()
# plt.show()
# import numpy as np
# from scipy.special import comb
# print(np.array([comb(25, i) * (0.2 ** i) * ((1 - 0.2) ** (25 - i)) for i in range(13, 26)]).sum())
# rfc = RandomForestClassifier(n_estimators=20,random_state=2)#随机森林中的random_state是形成固定的森林
# rfc = rfc.fit(Xtrain, Ytrain)
# print(rfc.estimators_)#estimators_用于观察随机森林中每一棵树的参数
# for i in range(len(rfc.estimators_)):
# print(rfc.estimators_[i].random_state)#森林中每一棵树的random_state是不同的,但是被固定了
# rfc = RandomForestClassifier(n_estimators=25,oob_score=True)#oob_score默认为False
# rfc = rfc.fit(wine.data,wine.target)#无需划分训练集和测试集
# print(rfc.oob_score_)
# rfc = RandomForestClassifier(n_estimators=25)
# rfc = rfc.fit(Xtrain, Ytrain)
# print(rfc.score(Xtest, Ytest))
# print(rfc.feature_importances_ ) # 结合zip可以对照特征名字查看特征重要性,参见上节决策树
# print(rfc.apply(Xtest) )# apply返回每个测试样本所在的叶子节点的索引
# print(rfc.predict(Xtest)) # predict返回每个测试样本的分类/回归结果
# print(rfc.predict_proba(Xtest))#每一个样本对应的被分到每一个标签的概率
# import numpy as np
# x = np.linspace(0, 1, 20)
# y = []
# for epsilon in np.linspace(0, 1, 20):
# E = np.array([comb(25, i) * (epsilon ** i) * ((1 - epsilon) ** (25 - i)) for i in range(13, 26)]).sum()
# y.append(E)
# plt.plot(x, y, "o-", label="when estimators are different")
# plt.plot(x, x, "--", color="red", label="if all estimators are same")
# plt.xlabel("individual estimator's error")
# plt.ylabel("RandomForest's error")
# plt.legend()
# plt.show()
from sklearn.datasets import load_boston # 一个标签是连续西变量的数据集
from sklearn.model_selection import cross_val_score # 导入交叉验证模块
from sklearn.ensemble import RandomForestRegressor # 导入随机森林回归器
boston = load_boston()
regressor = RandomForestRegressor(n_estimators=100, random_state=0) # 随机森林回归器实例化
print(cross_val_score(regressor, boston.data, boston.target, cv=10#导入全部数据,10折交叉验证
, scoring="neg_mean_squared_error" # 如果不设置scoring,回归评估默认是R平方,分类中评估是准确率
))
import sklearn
print(sorted(sklearn.metrics.SCORERS.keys()))#这些指标是scoring可选择的参数,可以用来参考
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#交叉验证
dataset = load_boston()
X_full, y_full = dataset.data, dataset.target
n_samples = X_full.shape[0]#506
n_features = X_full.shape[1]#13
rng = np.random.RandomState(0)#设置一个随机种子,方便观察
print(rng)
missing_rate = 0.5
n_missing_samples = int(np.floor(n_samples * n_features * missing_rate))#3289,np.floor向下取整,返回.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#把这3289个位置赋为nan
print(X_missing)
X_missing = pd.DataFrame(X_missing)#转换成DataFrame是为了后续方便各种操作,numpy对矩阵的运算速度快到拯救人生,但是在索引等功能上却不如pandas来得好用
print(X_missing.head())
imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')#实例化,使用均值进行填补
X_missing_mean = imp_mean.fit_transform(X_missing)#特殊的接口fit_transform = 训练fit + 导出predict
print(pd.DataFrame(X_missing_mean).isnull().sum())#如果求和为0可以彻底确认是否有NaN
imp_0 = SimpleImputer(missing_values=np.nan, strategy="constant",fill_value=0)#实例化,constant指的是常数,把数据为np.nan的填充为0
X_missing_0 = imp_0.fit_transform(X_missing)
print(X_missing_0)
X_missing_reg = X_missing.copy()
sortindex = np.argsort(X_missing_reg.isnull().sum(axis=0)).values#找出数据集中,缺失值从小到大排列的特征们的顺序,并且有了这些的索引,np.argsort()返回的是从小到大排序的顺序所对应的索引
print(np.argsort(X_missing_reg.isnull().sum(axis=0)))
print(sortindex)
for i in sortindex:
# 构建我们的新特征矩阵(没有被选中去填充的特征 + 原始的标签)和新标签(被选中去填充的特征),注意这里都是x没有y
df = X_missing_reg#避免X_missing_reg被填上0
fillc = df.iloc[:, i] # 新标签,可以理解为这里的y
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)#用SimpleImputer给nan特征值赋值为0,先实例化再fit_transform
print(pd.DataFrame(df_0))
# 找出我们的训练集和测试集
Ytrain = fillc[fillc.notnull()] # Ytrain是被选中要填充的特征中(现在是我们的标签),存在的那些值:非空值
Ytest = fillc[fillc.isnull()] # Ytest 是被选中要填充的特征中(现在是我们的标签),不存在的那些值:空值。注意我们需要的不是Ytest的值,需要的是Ytest所带的索引
Xtrain = df_0[Ytrain.index, :] # 在新特征矩阵上,被选出来的要填充的特征的非空值所对应的记录
Xtest = df_0[Ytest.index, :] # 在新特征矩阵上,被选出来的要填充的特征的空值所对应的记录
# 用随机森林回归来填补缺失值
rfc = RandomForestRegressor(n_estimators=100) # 实例化
rfc = rfc.fit(Xtrain, Ytrain) # 导入训练集进行训练
Ypredict = rfc.predict(Xtest) # 用predict接口将Xtest导入,得到我们的预测结果(回归结果),就是我们要用来填补空值的这些值
# 将填补好的特征返回到我们的原始的特征矩阵中
X_missing_reg.loc[X_missing_reg.iloc[:, i].isnull(), i] = Ypredict
# 检验是否有空值
print(X_missing_reg.isnull().sum().sum())
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)
print(mse)
print([*zip(['Full data','Mean Imputation','Zero Imputation','Regressor Imputation'],mse)])
x_labels = ['Full data',
'Mean Imputation',
'Zero Imputation',
'Regressor Imputation']
colors = ['r', 'g', 'b', 'orange']
plt.figure(figsize=(12, 6))#画出画布
ax = plt.subplot(111)#添加子图
for i in np.arange(len(mse)):
ax.barh(i, mse[i],color=colors[i], alpha=0.6, align='center')#bar为条形图,barh为横向条形图,alpha表示条的粗度;align表示条放在哪里
ax.set_title('Imputation Techniques with Boston Data')
ax.set_xlim(left=np.min(mse) * 0.9,
right=np.max(mse) * 1.1)#设置x轴取值范围
ax.set_yticks(np.arange(len(mse)))#设置y轴
ax.set_xlabel('MSE')#x轴标题,也就是横轴标题
ax.set_yticklabels(x_labels)#设置y轴显示什么
plt.show()
十一.随机森林在乳腺癌数据上的调参
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
data = load_breast_cancer()
# print(data)
rfc = RandomForestClassifier(n_estimators=100,random_state=90)
score_pre = cross_val_score(rfc,data.data,data.target,cv=10,scoring="accuracy").mean()#交叉验证的分类默认scoring='accuracy',要导入完整的数据
print(score_pre)
# 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)#打印出最大的交叉验证分数及其对应的n_estimators的取值
# plt.figure(figsize=[20,5])
# plt.plot(range(1,201,10),scorel)
# 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)
# plt.show()
# # 调整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)
# print(GS.best_params_) # 显示调整出来的最佳参数
# print(GS.best_score_) # 返回调整好的最佳参数对应的准确率,结果显示max_depth把模型复杂度往左推,竟然让泛化误差增加了,所以应该让模型向右推
# # 调整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_)#结果显示max_features升高之后,泛化误差还是升高,说明模型复杂度向右推误差也增高
# # 调整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)
# print(GS.best_params_)
# print(GS.best_score_)
# 调整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)
# print(GS.best_params_)
# print(GS.best_score_)
# # 调整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_)
rfc = RandomForestClassifier(n_estimators=39, random_state=90)
score = cross_val_score(rfc, data.data, data.target, cv=10).mean()
print(score)
print(score - score_pre)