sklearn机器学习库(二)sklearn中的随机森林

news2024/11/17 9:40:57

sklearn机器学习库(二)sklearn中的随机森林

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

多个模型集成成为的模型叫做集成评估器(ensemble estimator),组成集成评估器的每个模型都叫做基评估器(base estimator)。通常来说,有三类集成算法:装袋法(Bagging),提升法(Boosting)和stacking。

  • 装袋法(Bagging)的核心思想是构建多个相互独立的评估器,然后对其预测进行平均或多数表决原则来决定集成评估器的结果。装袋法的代表模型就是随机森林

  • 提升法(Boosting)中,基评估器是相关的,是按顺序一一构建的。其核心思想是结合弱评估器的力量一次次对难以评估的样本
    进行预测,从而构成一个强评估器。提升法的代表模型有Adaboost和梯度提升树(GBDT)

sklearn中的集成算法模块ensemble

类的功能
ensemble.AdaBoostClassifierAdaBoost分类
ensemble.AdaBoostRegressorAdaboost回归
ensemble.BaggingClassifier装袋分类器
ensemble.BaggingRegressor装袋回归器
ensemble.ExtraTreesClassifierExtra-trees分类(超树,极端随机树)
ensemble.ExtraTreesRegressorExtra-trees回归
ensemble.GradientBoostingClassifier梯度提升分类
ensemble.GradientBoostingRegressor梯度提升回归
ensemble.IsolationForest隔离森林
ensemble.RandomForestClassifier随机森林分类
ensemble.RandomForestRegressor随机森林回归
ensemble.RandomTreesEmbedding完全随机树的集成
ensemble.VotingClassifier用于不合适估算器的软投票/多数规则分类器

集成算法中,有一半以上都是树的集成模型。

决策树的核心问题有两个,一个是如何找出正确的特征来进行分枝,二是树生长到什么时候应该停下。

  • 对于第一个问题,我们定义了用来衡量分枝质量的指标不纯度,分类树的不纯度用基尼系数或信息熵来衡量,回归
    树的不纯度用MSE均方误差来衡量。每次分枝时,决策树对所有的特征进行不纯度计算,选取不纯度最低的特征进
    行分枝,分枝后,又再对被分枝的不同取值下,计算每个特征的不纯度,继续选取不纯度最低的特征进行分枝。
  • 决策树非常容易过拟合,为了防止决策树的过拟合,我们要对决策树进行剪枝,sklearn中提供了大量的剪枝参数 。

1 RandomForestClassifier

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

sklearn.ensemble.RandomForestClassifier(
    n_estimators=100, 
    *, 
    criterion='gini', 
    max_depth=None, 
    min_samples_split=2, 
    min_samples_leaf=1, 
    min_weight_fraction_leaf=0.0, 
    max_features='sqrt', 
    max_leaf_nodes=None, 
    min_impurity_decrease=0.0, 
    bootstrap=True, 
    oob_score=False, 
    n_jobs=None, 
    random_state=None, 
    verbose=0, 
    warm_start=False, 
    class_weight=None, 
    ccp_alpha=0.0, 
    max_samples=None
)

1.1 重要参数

1.1.1 基评估器的控制参数

参数含义
criterion不纯度的衡量指标,{“gini”, “entropy”, “log_loss”},默认是”gini”
max_depth树的最大深度,超过最大深度的树枝都会被剪掉
min_samples_leaf一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,
min_samples_split一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生
max_featuresmax_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃, 默认值为总特征个数开平方取整(sqrt),可选值有**{“sqrt”, “log2”, None}**
min_impurity_decrease信息增益小于设定数值的分枝不会发生

详细解释可参考官网。https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html#sklearn.ensemble.RandomForestClassifier

1.1.2 n_estimators

  • 这是森林中树木的数量,即基评估器的数量。这个参数对随机森林模型的精确性影响是单调的,n_estimators越大,模型的效果往往越好

  • 但是相应的,任何模型都有决策边界,n_estimators达到一定的程度之后,随机森林的精确性往往不在上升或开始波动,并且,n_estimators越大,需要的计算量和内存也越大,训练的时间也会越来越长。对于这个参数,我们是渴望在训练难度和模型效果之间取得平衡。

  • n_estimators的默认值在0.22版本中,默认值从10改为100,这个修正显示出了使用者的调参倾向:要更大的n_estimators。

from matplotlib import pyplot as plt
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split,cross_val_score
%matplotlib inline


# 导入红酒数据集
wine = load_wine()

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)


tree_score = clf.score(Xtest,Ytest)
forest_score = rfc.score(Xtest,Ytest)

print('单棵树:{}'.format(tree_score),'随机森林:{}'.format(forest_score))
单棵树:0.9444444444444444 随机森林:1.0
# 交叉验证
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()

在这里插入图片描述

# n_estimators的学习曲线
forest_scores = []

for i in range(100):
    rfc = RandomForestClassifier(n_estimators=i+1)
    s = cross_val_score(rfc,wine.data,wine.target,cv=10).mean()
    forest_scores.append(s)


# 打印最大值及最大值的索引
print(max(forest_scores),forest_scores.index(max(forest_scores)))
plt.figure(figsize=(10,8))
plt.plot(range(1,101),forest_scores)
plt.legend()
plt.show()

在这里插入图片描述

1.1.3 random_state

  • 随机森林的本质是一种装袋集成算法(bagging),装袋集成算法是对基评估器的预测结果进行平均或用多数表决原则来决定集成评估器的结果。

  • 在刚才的红酒例子中,我们建立了25棵树,对任何一个样本而言,平均或多数表决原则下,当且仅当有13棵以上的树判断错误的时候,随机森林才会判断错误。单独一棵决策树对红酒数据集的分类准确率在0.85上下浮动,假设一棵树判断错误的可能性为0.2(ε),那20棵树以上都判断错误的可能性是0.000369。判断错误的几率非常小,这让随机森林在红酒数据集上的表现远远好于单棵决策树

在这里插入图片描述

  • 随机森林中其实也有random_state,用法和分类树中相似。
    • 只不过在分类树中,一个random_state只控制生成一棵树
    • 而随机森林中的random_state控制的是生成森林的模式,而非让一个森林中只有一棵树
rfc = RandomForestClassifier(n_estimators=20,random_state=2)
rfc = rfc.fit(Xtrain, Ytrain)

#随机森林的重要属性之一:estimators,查看森林中树的状况
for i in range(len(rfc.estimators_)):
    print(rfc.estimators_[i].random_state)
1872583848
794921487
111352301
1853453896
213298710
1922988331
......
  • 当random_state固定时,随机森林中生成是一组固定的树,但每棵树依然是不一致的,这是用随机挑选特征进行分枝的方法得到的随机性。并且我们可以证明,当这种随机性越大的时候,袋装法的效果一般会越来越好。用袋装法集成时,基分类器应当是相互独立的,是不相同的

  • 但这种做法的局限性是很强的,当我们需要成千上万棵树的时候,数据不一定能够提供成千上万的特征来让我们构筑尽量多尽量不同的树。因此,除了random_state。我们还需要其他的随机性

1.1.4 bootstrap & oob_score

  • 要让基分类器尽量都不一样,另一种很容易理解的方法是使用不同的训练集来进行训练,而袋装法正是通过有放回的随机抽样技术来形成不同的训练数据,bootstrap就是用来控制抽样技术的参数。

  • 在一个含有n个样本的原始训练集中,我们进行随机采样,每次采样一个样本,并在抽取下一个样本之前将该样本放回原始训练集,也就是说下次采样时这个样本依然可能被采集到,由于是随机采样,这样每次的自助集和原始数据集不同,和其他的采样集也是不同的。用这些自助集来训练我们的基分类器,我们的基分类器自然也就各不相同了。

  • bootstrap参数默认True,代表采用这种有放回的随机抽样技术。

  • 一般来说,自助集大约平均会包含63%的原始数据 。因此,会有约37%的训练数据被浪费掉,没有参与建模,这些数据被称为袋外数据(out of bag data,简写为oob)

1 − ( 1 − 1 / n ) n 当 n 足够大时,这个概率收敛于 1 − ( 1 / e ) ,约等于 0.632 。 1-(1-1/n)^n \\ 当n足够大时,这个概率收敛于1-(1/e),约等于0.632。 1(11/n)nn足够大时,这个概率收敛于1(1/e),约等于0.632

  • 在使用随机森林时,我们可以不划分测试集和训练集,只需要用袋外数据来测试我们的模型即可。
    • 当然,这也不是绝对的,当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_
print(rfc.oob_score_) 

1.2 重要接口

  • 随机森林的接口与决策树完全一致,因此依然有四个常用接口:apply, fit, predict和score

  • 除此之外,还需要注意随机森林的predict_proba接口,这个接口返回每个测试样本对应的被分到每一类标签的概率,标签有几个分类就返回几个概率。如果是二分类问题,则predict_proba返回的数值大于0.5的,被分为1,小于0.5的,被分为0。

  • 传统的随机森林是利用袋装法中的规则,平均或少数服从多数来决定集成的结果,而sklearn中的随机森林是平均每个样本对应的predict_proba返回的概率,得到一个平均概率,从而决定测试样本的分类

在这里插入图片描述

在这里插入图片描述

注意:

当基分类器的误差率小于0.5,即准确率大于0.5时,集成的效果是比基分类器要好的。

相反,当基分类器的误差率大于0.5,袋装的集成算法就失效了。

所以在使用随机森林之前,一定要检查,用来组成随机森林的分类树们是否都有至少50%的预测正确率。

2 RandomForestRegressor

DecisionTreeRegressor(*,
                      criterion='squared_error', 
                      splitter='best', 
                      max_depth=None, 
                      min_samples_split=2, 
                      min_samples_leaf=1, 
                      min_weight_fraction_leaf=0.0, 
                      max_features=None, 
                      random_state=None, 
                      max_leaf_nodes=None, 
                      min_impurity_decrease=0.0, 
                      ccp_alpha=0.0
)

所有的参数,属性与接口,全部和随机森林分类器一致。仅有的不同就是回归树与分类树的不同,不纯度的指标,
参数Criterion不一致。

2.1 Criterion

Criterion是衡量回归树分枝质量的指标 :

  • 均方误差的squared_error,父节点和叶子节点之间的均方误差的差额将被用来作为特征选择的标准,这种方法通过使用叶子节点的均值来最小化L2损失

  • friedman_mse,这种指标使用弗里德曼针对潜在分枝中的问题改进后的均方误差

  • 平均绝对误差absolute_error,这种指标使用叶节点的中值来最小化L1损失

  • 以及poisson,它使用泊松偏差的减少来寻找分裂

虽然均方误差永远为正,但是sklearn当中使用均方误差作为评判标准时,却是计算负均方误差

这是因为sklearn在计算模型评估指标的时候,会考虑指标本身的性质,均方误差本身是一种误差,所以被sklearn划分为模型的一种损失(loss),因此在sklearn当中,都以负数表示。真正的均方误差MSE的数值,其实就是neg_mean_squared_error去掉负号的数字 。

# 读取波士顿数据集,注意:新版本的sklearn中自带的已经删除
data = pd.read_csv("boston_housing.data", sep='\s+', header=None)

x = data.iloc[:, :-1]
y = data.iloc[:, -1]


regressor = RandomForestRegressor(n_estimators=100,random_state=0)
cross_val_score(regressor, x, y, cv=10,scoring = "neg_mean_squared_error")

在这里插入图片描述

返回十次交叉验证的结果,注意在这里,如果不填写scoring = “neg_mean_squared_error”,交叉验证默认的模型衡量指标是R平方,因此交叉验证的结果可能有正也可能有负。

而如果写上scoring,则衡量标准是负MSE,交叉验证的结果只可能为负。

2.2 使用随机森林填补缺失值

我们从现实中收集的数据,往往都会有一些缺失值。面对缺失值,很多人选择的方式是直接将含有缺失值的样本删除,这是一种有效的方法。

有时候填补缺失值会比直接丢弃样本效果更好。在sklearn中,我们用sklearn.impute.SimpleImputer来轻松地将均值,中值,或者其他最常用的数值填补到数据中。

在这个案例中,我们将使用均值,0,和随机森林回归来填补缺失值,并验证四种状况下的拟合状况,找出对使用的数据集来说最佳的缺失值填补方法。

import numpy as np
import pandas as pd
from sklearn.impute import SimpleImputer
import matplotlib.pyplot as plt
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import cross_val_score

# 读取波士顿数据集,注意:新版本的sklearn中自带的已经删除
data = pd.read_csv("boston_housing.data", sep='\s+', header=None)

x = data.iloc[:, :-1]
y = data.iloc[:, -1]

print(x.shape)
x.info()  # 均非空

在这里插入图片描述

# 人为填充缺失值
#所有数据要随机遍布在数据集的各行各列当中,而一个缺失的数据会需要一个行索引和一个列索引
#如果能够创造一个数组,包含3289个分布在0~506中间的行索引,和3289个分布在0~13之间的列索引,那我们就可以利用索引来为数据中的任意3289个位置赋空值

n_samples = x.shape[0]
n_features = x.shape[1]

rng = np.random.RandomState(0)
miss_rate = 0.5 # 缺失50%,即3289数据

n_missing_samples = int(np.floor(n_samples * n_features * miss_rate))

missing_features = rng.randint(0,n_features,n_missing_samples)
missing_samples = rng.randint(0,n_samples,n_missing_samples)
X_missing = x.copy().to_numpy()
y_missing = y.copy()
X_missing[missing_samples,missing_features] = np.nan
X_missing = pd.DataFrame(X_missing)


X_missing.head(10)

在这里插入图片描述

# 使用0和均值填补缺失值

# 1、使用均值进行填充
s_mean = SimpleImputer(missing_values=np.nan, strategy='mean')

x_miss_mean = s_mean.fit_transform(X_missing)


# 2、使用常数0进行填充
zero_mean = SimpleImputer(missing_values=np.nan, strategy='constant',fill_value=0)

x_miss_zero = zero_mean.fit_transform(X_missing)

# 3、使用随机森林填充缺失值
'''
特征T不缺失的值对应的其他n-1个特征 + 本来的标签:X_train
特征T不缺失的值:Y_train

特征T缺失的值对应的其他n-1个特征 + 本来的标签:X_test
特征T缺失的值:未知,我们需要预测的Y_test

这种做法,对于某一个特征大量缺失,其他特征却很完整的情况,非常适用

那如果数据中除了特征T之外,其他特征也有缺失值怎么办?
答案是遍历所有的特征,从缺失最少的开始进行填补(因为填补缺失最少的特征所需要的准确信息最少)。
填补一个特征时,先将其他特征的缺失值用0代替,每完成一次回归预测,就将预测值放到原本的特征矩阵中,
再继续填补下一个特征。每一次填补完毕,有缺失值的特征会减少一个,所以每次循环后,需要用0来填补的特征就越来越少

'''
X_missing_reg = X_missing.copy()
sortindex = np.argsort(X_missing_reg.isnull().sum(axis=0))

for i in sortindex:
    #构建我们的新特征矩阵和新标签
    df = X_missing_reg
    fillc = df.iloc[:,i]
    df = pd.concat([df.iloc[:,df.columns != i],y],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
# 对填补好的数据进行建模
X = [x,x_miss_mean,x_miss_zero,X_missing_reg]


mse = []
std = []
for x in X:
    estimator = RandomForestRegressor(random_state=0, n_estimators=100)
    scores = cross_val_score(estimator,x,y,scoring='neg_mean_squared_error',cv=5).mean()
    mse.append(scores * -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)):
    ax.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()

在这里插入图片描述

3 泛化误差详解

模型调参,第一步是要找准目标:我们要做什么?

一般来说,这个目标是提升某个模型评估指标,比如对于随机森林来说,我们想要提升的是模型在未知数据上的准确率(由score或oob_score_来衡量)。

找准了这个目标,我们就需要思考:模型在未知数据上的准确率受什么因素影响?

在机器学习中,我们用来衡量模型在未知数据上的准确率的指标,叫做泛化误差(Genelization error)

3.1 泛化误差与模型结构的关系

当模型在未知数据(测试集或者袋外数据)上表现糟糕时,我们说模型的泛化程度不够,泛化误差大,模型的效果
不好。泛化误差受到模型的结构(复杂度)影响。

如下图:

  • 当模型太复杂,模型就会过拟合,泛化能力就不够,所以泛化误差大。

  • 当模型太简单,模型就会欠拟合,拟合能力就不够,所以误差也会大。

  • 只有当模型的复杂度刚刚好的才能够达到泛化误差最小的目标

在这里插入图片描述

模型的复杂度与参数的关系

  • 对树模型来说,树越茂盛,深度越深,枝叶越多,模型就越复杂

  • 所以树模型是天生位于图的右上角的模型,随机森林是以树模型为基础,所以随机森林也是天生复杂度高的模型。随机森林的参数,都是向着一个目标去:减少模型的复杂度,把模型往图像的左边移动,防止过拟合

  • 当然了,调参没有绝对,也有天生处于图像左边的随机森林,所以调参之前,我们要先判断,模型现在究竟处于图像的哪一边。

3.2 随机森林与泛化误差

我们现在已经知道:

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

3.3 方差与偏差

集成模型在未知数据集上的泛化误差E,由方差(var),偏差(bais)和噪声(ε)共同决定。

偏差:模型的预测值与真实值之间的差异,模型越精确,偏差越低。

方差:反映的是模型每一次输出结果与模型预测值的平均水平之间的误差,模型越稳定,方差越低。

其中偏差衡量模型是否预测得准确,偏差越小,模型越“准”;而方差衡量模型每次预测的结果是否接近,即是说方
差越小,模型越“稳” 。

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

泛化误差和方差及偏差的关系

在这里插入图片描述

  • 模型复杂度大的时候,方差高,偏差低。

    • 偏差低,就是要求模型要预测得“准”。模型就会更努力去学习更多信息,会具体于训练数据,这会导致,模型在一部分数据上表现很好,在另一部分数据上表现却很糟糕。
    • 模型泛化性差,在不同数据上表现不稳定,所以方差就大。而要尽量学习训练集,模型的建立必然更多细节,复杂程度必然上升。所以,复杂度高,方差高,总泛化误差高。
  • 相对的,复杂度低的时候,方差低,偏差高。

    • 方差低,要求模型预测得“稳”,泛化性更强,那对于模型来说,它就不需要对数据进行一个太深的学习,只需要建立一个比较简单,判定比较宽泛的模型就可以了。
    • 结果就是,模型无法在某一类或者某一组数据上达成很高的准确度,所以偏差就会大。所以,复杂度低,偏差高,总泛化误差高。

随机森林中的方差与偏差

随机森林的基评估器都拥有较低的偏差和较高的方差,因为决策树本身是预测比较”准“,比较容易过拟合的模型,装袋法本身也要求基分类器的准确率必须要有50%以上。

所以以随机森林为代表的装袋法的训练过程旨在降低方差,即降低模型复杂度,所以随机森林参数的默认设定都是假设模型本身在泛化误差最低点的右边

4 随机森林在乳腺癌数据集上的调参

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()

# 乳腺癌数据集有569条记录,30个特征,单看维度虽然不算太高,但是样本量非常少。过拟合的情况可能存在
data.data.shape
# 进行一次简单的建模,看看模型本身在数据集上的效果
rfc = RandomForestClassifier(n_estimators=100,random_state=20)
score_pre = cross_val_score(rfc,data.data,data.target,cv=10).mean()

print(score_pre)  # 0.9648809523809524
# 随机森林调整的第一步:无论如何先来调n_estimators

scorel = []
for i in range(0,200,10):
    rfc = RandomForestClassifier(n_estimators=i+1,
                                 n_jobs=-1,
                                 random_state=20)
    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()

在这里插入图片描述

# 在确定好的范围内,进一步细化学习曲线
scorel = []
for i in range(45,80):
    rfc = RandomForestClassifier(n_estimators=i,
                                 n_jobs=-1,
                                 random_state=20)
    score = cross_val_score(rfc,data.data,data.target,cv=10).mean()
    scorel.append(score)

print(max(scorel),([*range(45,80)][scorel.index(max(scorel))]))
plt.figure(figsize=[20,5])
plt.plot(range(45,80),scorel)
plt.show()

在这里插入图片描述

# 接下来就进入网格搜索,使用网格搜索对参数一个个进行调整。
# 为什么我们不同时调整多个参数呢?
# 1)同时调整多个参数会运行非常缓慢。
# 2)同时调整多个参数,会让我们无法理解参数的组合是怎么得来的,所以即便网格搜索调出来的结果不好,我们也不知道从哪里去改。
# 在这里,为了使用复杂度-泛化误差方法(方差-偏差方法),我们对参数进行一个个地调整。


# 为网格搜索做准备,书写网格搜索的参数
"""
有一些参数是没有参照的,很难说清一个范围,这种情况下我们使用学习曲线,看趋势从曲线跑出的结果中选取一个更小的区间,再跑曲线

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)}


有一些参数是可以找到一个范围的,或者说我们知道他们的取值和随着他们的取值,模型的整体准确率会如何变化,这样的参数我们就可以直接跑网格搜索

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(1,30,1)}
"""

# 按照参数对模型整体准确率的影响程度进行调参,首先调整max_depth

# 调整max_depth
param_grid = {'max_depth':np.arange(1, 20, 1)}

# 一般根据数据的大小来进行一个试探,乳腺癌数据很小,所以可以采用1~10,或者1~20这样的试探
# 但对于大型数据来说,我们应该尝试30~50层深度(或许还不足够更应该画出学习曲线,来观察深度对模型的影响)
rfc = RandomForestClassifier(n_estimators=59,random_state=20)

GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_) # 模型评分和之前一模一样,说明已经在最佳参数了,无需再调了

#{'max_depth': 9}
#0.968421052631579
# 调整max_features
param_grid = {'max_features':np.arange(1,30,1)}
"""
max_features是唯一一个即能够将模型往左(低方差高偏差)推,也能够将模型往右(高方差低偏差)推的参数。

max_features的默认最小值是sqrt(n_features)。
"""
rfc = RandomForestClassifier(n_estimators=59
                                ,random_state=20
                                )

GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)

print(GS.best_params_)
print(GS.best_score_)  # 最佳模型评分和之前一模一样,说明模型达到了上限
# {'max_features': 5}
# 0.968421052631579

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/887141.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMq-1基础概念

RabbitMq-----分布式中的一种通信手段 1. MQ的基本概念(message queue,消息队列) mq:消息队列,存储消息的中间件 分布式系统通信的两种方式:直接远程调用,借助第三方完成间接通信 消息的发送方是生产者&#xff0c…

爬虫逆向实战(九)--猿人学第十三题

一、数据接口分析 主页地址:猿人学第十三题 1、抓包 通过抓包可以发现数据接口是api/match/13 2、判断是否有加密参数 请求参数是否加密? 无请求头是否加密? 无响应是否加密? 无cookie是否加密? 在“cookie”模块…

python数据分析需要学哪些,python数据分析要学多久

大家好,小编为大家解答python数据分析应该学什么软件的问题。很多人还不知道python数据分析需要什么基础,现在让我们一起来看看吧! 根据调查结果,十大最常用的数据工具中有八个来自或利用Python。Python广泛应用于所有数据科学领域…

STM32 FLASH 读写数据

1. 《STM32 中文参考手册》,需要查看芯片数据手册,代码起始地址一般都是0x8000 0000,这是存放整个项目代码的起始地址 2. 编译信息查看代码大小,修改代码后第一次编译后会有这个提示信息 2.1 修改代码后编译,会有提示…

物联网在制造业中的应用

制造业目前正在经历第四次工业革命,物联网、人工智能和机器人等技术进步正在推动行业的发展。研究表明,到2024年,全球制造商将在物联网解决方案上投资700亿美元,许多制造商正在实施物联网设备,以利用预测性维护和复杂的…

优化GitHub网站访问慢的问题

方法一、修改host文件解决 大型网站服务器都不会是只有一台服务器,而是多台服务器组成的集群一起对外提供服务。 使用站长工具测速,找一个速度比较快的服务器。 图中可以看到140.82.121.4这个ip比较快, 下面修改hosts: Mac 在 /etc/hosts 中&#x…

.net连接mysql,提示找不到请求的 .Net Framework Data Provider。可能没有安装

开发完成的.net程序需要连接mysql数据库,在个人电脑上运行没问题,别人运行时提示“提示找不到请求的 .Net Framework Data Provider。可能没有安装”。经过查询,安装Connector/NET 8.1.0,下载地址如下所示: https://d…

Mac OS minicom 无法设置921600问题

MacOS minicom 无法设置921600问题 介绍过程解决方案参考资料 介绍 minicom是Mac上一款非常好用的串口工具。本文假设你已经安装minicom,并且知道minicom的一般配置和使用方法。这是“MacOS minicom 无法设置921600”的解决问题记录。它在以下环境中设置成功&#…

【制作npm包1】申请npm账号、认识个人包和组织包

概述 在开发当中经常有一种现象,重复代码写了N多遍,再次写同样的逻辑就再次翻查以前的代码逻辑。效率低下且容易出错,封装一个npm包的价值也不仅仅是给别人用,封装一套属于自己或者本部门的npm包也是相当有必要。 也许经常看到一…

fastadmin 自定义按钮弹窗不是异步xhr提交

遇到一个奇怪的问题 按官方文档要求,js中也重新绑定事件了 但弹窗出来的表单还不是xhr提交,这为什么? 经过我不断测试发现,如上述的方法名不能带有下划线,蛇形大小写,否则一律不生效。 浪费了我一天半时…

小程序CSS button按钮自定义高度之后不居中

问题&#xff1a; 按钮设置高度后不居中 <view><button class"btn1" size"">Save</button> </view> page {font-size: 30rpx; }.btn1 {margin-top: 100rpx;height: 190rpx;background: linear-gradient(90deg, #FF8A06, #FF571…

webSocket 聊天室 node.js 版

全局安装vue脚手架 npm install vue/cli -g 创建 vue3 ts 脚手架 vue create vue3-chatroom 后端代码 src 同级目录下建 server: const express require(express); const app express(); const http require(http); const server http.createServer(app);const io req…

微信小程序:模板使用

目录 模板的优点&#xff1a; 一、静态模板创建 二、静态模板使用 1.*.wxml引入模板 2.模板使用 3.*.wxss引入模板的样式 三、动态模板创建 四、动态模板使用 1.*.wxml引入模板 2.模板使用 3.*.js定义动态数据 五、结果展示 总结 模板的优点&#xff1a; 有利于保持网…

第二章 搜索 No.1BFS之Flood Fill与最短路模型

文章目录 Flood Fill算法1097. 池塘计数1098. 城堡问题1106. 山峰和山谷 最短路模型1076. 迷宫问题188. 武士风度的牛1100. 抓住那头牛 Flood Fill算法 可以在线性时间复杂度内&#xff0c;找到某个点所在的连通块 想象一个矩阵&#xff0c;有洼地和高地&#xff0c;选择一个洼…

经验分享:企业数据仓库建设方案总结!

导读 在企业的数字化转型浪潮中&#xff0c;数据被誉为“新时代的石油”&#xff0c;而数据仓库作为数据管理与分析的核心基础设施&#xff0c;在企业的信息化建设中扮演着重要的角色。本文将深入探讨企业数据仓库建设过程中所遇到的问题以及解决经验&#xff0c;为正在筹备或…

微信程序 自定义遮罩层遮不住底部tabbar解决

一、先上效果 二 方法 1、自定义底部tabbar 实现&#xff1a; https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html 官网去抄 简单写下&#xff1a;在代码根目录下添加入口文件 除了js 文件的list 需要调整 其他原封不动 代码&#xf…

电脑键盘打不了字按哪个键恢复?最新分享!

“有没有朋友知道电脑键盘为什么会莫名其妙就打不了字&#xff1f;明明用得好好的&#xff0c;突然就打不了字了&#xff0c;真的让人很迷惑&#xff01;有什么方法可以解决吗&#xff1f;” 电脑键盘为我们的办公提供了很大的方便&#xff0c;我们可以利用键盘输入我们需要的文…

如何用树莓派Pico针对IoT编程?

目录 一、Raspberry Pi Pico 系列和功能 二、Raspberry Pi Pico 的替代方案 三、对 Raspberry Pi Pico 进行编程 硬件 软件 第 1 步&#xff1a;连接计算机 第 2 步&#xff1a;在 Pico 上安装 MicroPython 第 3 步&#xff1a;为 Thonny 设置解释器 第 4 步&#xff…

深度学习实战48-【未来的专家团队】基于AutoCompany模型的自动化企业概念设计与设想

大家好,我是微学AI,今天给大家介绍一下深度学习实战48-【未来的专家团队】基于AutoCompany模型的自动化企业概念设计与设想,文本将介绍AutoCompany模型的概念设计,涵盖了AI智能公司的各个角色,并结合了GPT-4接口来实现各个角色的功能,设置中央控制器,公司运作过程会生成…

GitKraken保姆级图文使用指南

前言 写这篇文章的原因是组内的产品和美术同学&#xff0c;开始参与到git工作流中&#xff0c;但是网上又没有找到一个比较详细的使用教程&#xff0c;所以干脆就自己写了一个[doge]。文章的内容比较基础&#xff0c;介绍了Git内的一些基础概念和基本操作&#xff0c;适合零基…