随机森林笔记

随机森林

概述

集成算法

不是一个单独的学习算法,而是通过在数据上构建多个模型,集成所有模型的建模结果。

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

多个模型集成成为的模型叫做集成评估器,其中的每个模型都叫做基评估器。

有三类集成算法:装袋法(Bagging),提升法(Boosting),Stacking

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

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

ensemble.RandomForestClassifier随机森林分类
ensemble.RandomForestRegressor随机森林回归

随机森林分类树

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

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

n_estimators

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

random_state

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

根据公式计算可得,判断错的概率非常小,因此随机森林的效果远好于决策树。

随机森林的random_state决定的是一片固定的森林,决策树的random_state决定的是一棵固定的树。

rfc = RandomForestClassifier(n_estimators=20,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)
    
# 每一棵树的random_state都不一样

当random_state固定时,随机森林中生成是一组固定的树,但每棵树依然是不一致的,这是 用”随机挑选特征进行分枝“的方法得到的随机性。并且我们可以证明,当这种随机性越大的时候,袋装法的效果一 般会越来越好。用袋装法集成时,基分类器应当是相互独立的,是不相同的。

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

bootstrap & oob_score

bootstrap用来控制抽样技术的参数。

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然而有放回抽样也会有自己的问题。由于是有放回,一些样本可能在同一个自助集中出现多次,而其他一些却可能 被忽略,一般来说,自助集大约平均会包含63%的原始数据。因为每一个样本被抽到某个自助集中的概率为:

1 - (1-1/n)^n

当n足够大时,就会收敛于1-(1/e)。因会有(1/e)的数据被浪费掉,没有参与建模,此时这些数据被称为袋外数据(简称为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_

随机森林回归树

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不一致。

重要参数,属性与接口

# sklearn当中的模型评估指标列表,显示所有评估指标
import sklearn
sorted(sklearn.metrics.SCORERS.keys())

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

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
  1. 导入数据集
dataset = load_boston()
#数据集为506*13的矩阵
#总共506*13=6578个数据
dataset.data.shape

# 将数据填入充实的数据集中
X_full, y_full = dataset.data, dataset.target

# 数据的行数为样本数,数据的列数为特征数
n_samples = X_full.shape[0]
n_features = X_full.shape[1]
  1. 将完整的数据变为含有缺失值的数据
#首先确定我们希望放入的缺失数据的比例,在这里我们假设是50%,那总共就要有3289个数据缺失
rng = np.random.RandomState(0) # 随机种子
missing_rate = 0.5 # 缺失比例

#np.floor向下取整,返回.0格式的浮点数
#所有数据要随机遍布在数据集的各行各列当中,而一个缺失的数据会需要一个行索引和一个列索引
#如果能够创造一个数组,包含3289个分布在0~506中间的行索引,和3289个分布在0~13之间的列索引,那我们就可以利用索引来为数据中的任意3289个位置赋空值
n_missing_samples = int(np.floor(n_samples * n_features * missing_rate)) # 缺失个数

#然后我们用0,均值和随机森林来填写这些缺失值,然后查看回归的结果如何
#(上限,下限,n)在上限和下限中取出n个整数 
missing_features = rng.randint(0,n_features,n_missing_samples)
missing_samples = rng.randint(0,n_samples,n_missing_samples)

#我们现在采样了3289个数据,远远超过我们的样本量506,所以我们使用随机抽取的函数randint。
#但如果我们需要的数据量小于我们的样本量506,那我们可以采用np.random.choice来抽样,choice会随机抽取不重复的随机数,
#因此可以帮助我们让数据更加分散,确保数据不会集中在一些行中
#missing_samples = rng.choice(dataset.data.shape[0],n_missing_samples,replace=False)

# 将正确的数值变为缺失的数值
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来得好用

dataframe就是表格数据,方便查看。注意和矩阵数据的区别。

  1. 使用0和均值填补缺失值

在上一步中将数据变为了含有缺失值的数据,此步骤将使用SimpleImputer对数据进行填补.

#使用均值进行填补
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)

# missing_values需要填补值的原始数据
  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_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()

机器学习的调参思想

学习曲线,网格搜索…通过以上方法来调整模型的取值,找到得分最高的点。网格搜索较为缓慢,有时的结果会比手动调整的结果好。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值