1、定义:集成学习(ensemble learning)本身不是一个单独的机器学习算法,而是通过在数据上构建多个模型,集成所有模型的建模结果。
2、举例:在现在的各种算法竞赛中,集成算法包括随机森林,梯度提升树(GBDT),Xgboost等。
3、目标:集成算法会考虑多个评估器的建模结果,汇总之后得到一个综合的结果,以此来获取比单个模型更好的回归或分类表现。
4、分类:通常来说,有三类集成算法:装袋法(Bagging),提升法(Boosting)和stacking。
(1)装袋法:装袋法的核心思想是构建多个相互独立的评估器,然后对其预测进行平均或多数表决原则来决定集成评估器的结果。装袋法的代表模型就是随机森林。
(2)提升法:提升法中,基评估器是相关的,是按顺序一一构建的。其核心思想是结合弱评估器的力量一次次对难以评估的样本进行预测,从而构成一个强评估器。提升法的代表模型有Adaboost和梯度提升树。
5、集成评估器:多个模型集成成为的模型叫做集成评估器(ensemble estimator)。
6、基评估器:组成集成评估器的每个模型都叫做基评估器(base estimator)。
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 | 用于不合适估算器的软投票/多数规则分类器 |
随机森林是非常具有代表性的Bagging集成算法,它的所有基评估器都是决策树,分类树组成的森林就叫做随机森林分类器,回归树所集成的森林就叫做随机森林回归器
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)
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
(1)定义:这是森林中树木的数量,即基评估器的数量。
(2)效果:这个参数对随机森林模型的精确性影响是单调的,n_estimators越大,模型的效果往往越好。n_estimators达到一定的程度之后,随机森林的精确性往往不在上升或开始波动,并且,n_estimators越大,需要的计算量和内存也越大,训练的时间也会越来越长。对于这个参数,我们应该在训练难度和模型效果之间取得平衡。
3、random_state
当random_state固定时,随机森林中生成是一组固定的树,但每棵树依然是不一致的,这是
用”随机挑选特征进行分枝“的方法得到的随机性。并且我们可以证明,当这种随机性越大的时候,袋装法的效果一般会越来越好。用袋装法集成时,基分类器应当是相互独立的,是不相同的。
**rfc.estimators_**查看随机森林中每一个树详细情况
4、 bootstrap
bootstrap就是用来控制抽样技术的参数。bootstrap参数默认True,代表采用这种有放回的随机抽样技术(有放回抽样也会有自己的问题。由于是有放回,一些样本可能在同一个自助集中出现多次,而其他一些却可能被忽略,自助集大约平均会包含63%的原始数据。),通常,这个参数不会被我们设置为False
5、oob_score
会有约37%的训练数据被浪费掉,没有参与建模,这些数据被称为袋外数据(out of bag data,简写为oob)。除了我们最开始就划分好的测试集之外,这些数据也可以被用来作为集成算法的测试集。也就是说,在使用随机森林时,我们可以不划分测试集和训练集,只需要用袋外数据来测试我们的模型即可。如果希望用袋外数据来测试,则需要在实例化时就将oob_score这个参数调整为True
oob_score_来查看我们的在袋外数据上测试的结果
rfc=RandomForestClassifier(n_estimators=15,oob_score=True)
rfc=rfc.fit(wine.data,wine.target)
print(rfc.oob_score_)
常用接口:apply, fit, predict和score和决策树相同用法。
predict_proba接口:返回每个测试样本对应的被分到每一类标签的概率,标签有几个分类就返回几个概率(如果时二分类,则predict_proba返回的数值大于0.5的,被分为1,小于0.5的,被分为0)
1、导入模块包以及红酒数据集
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
wine=load_wine()
2、sklearn建模(非交叉验证)
#sklearn建模
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(Xtrain,Ytrain)
print("Single Tree:{}",format(score_c)
,"Random Forest:{}",format(score_r))
#随机森林
rfc=RandomForestClassifier(n_estimators=25)
rfc_s=cross_val_score(rfc,wine.data,wine.target,cv=10)
#决策树
clf=DecisionTreeClassifier(random_state=0)
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()
输出结果:
可以看出随机森林的得分普遍高于决策树。
4、 随机森林和决策树在十组交叉验证下的效果对比
rfc_l = []
clf_l = []
for i in range(10):
rfc = RandomForestClassifier(n_estimators=25)
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()
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()
输出结果:
当n_estimators=15时,得分最高,为0.988
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不同,具体参考决策树。决策树详解
与随机森林相比不存在predict_proba接口
在sklearn中,我们可以使用sklearn.impute.SimpleImputer将均值,中值,或者其他最常用的数值填补到数据中,在这个案例中,我们将使用均值,0,和随机森林回归来填补缺失值,并验证四种状况下的拟合状况,找出对使用的数据集来说最佳的缺失值填补方法。在这里我们采用sklearn中波士顿房价数据集。
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
dataset=load_boston()
#记录非缺失值
X_full, y_full = dataset.data, dataset.target
n_samples = X_full.shape[0]
n_features = X_full.shape[1]
2、随机获取缺失值。
由于波士顿房价数据集中无缺失值,因此我们随机选取波士顿房价数据集中的数据,并将其更改为NAN
#放入缺失值
#首先确定我们希望放入的缺失数据的比例,在这里我们假设是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格式的浮点数
#随机生成缺失值的行索引和列索引
missing_features = rng.randint(0,n_features,n_missing_samples)
missing_samples = rng.randint(0,n_samples,n_missing_samples)
#将缺失值更改为NAN,并且写入数据表
X_missing = X_full.copy()
y_missing = y_full.copy()
X_missing[missing_samples,missing_features] = np.nan
X_missing = pd.DataFrame(X_missing)
#使用0填补缺失值
imp_0 = SimpleImputer(missing_values=np.nan, strategy="constant",fill_value=0)
X_missing_0 = imp_0.fit_transform(X_missing)
pd.DataFrame(X_missing_0).isnull().sum()
#使用均值填补缺失值
imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
X_missing_mean = imp_mean.fit_transform(X_missing)
pd.DataFrame(X_missing_mean).isnull().sum()
输出结果:
5、随机森林填补缺失值
(1)随机森林回归填补缺失值原理:任何回归都是从特征矩阵中学习,然后求解连续型标签y的过程,之所以能够实现这个过程,是因为回归算法认为,特征矩阵和标签之前存在着某种联系。实际上,标签和特征是可以相互转换的,比如说,在一个“用地区,环境,附近学校数量”预测“房价”的问题中,我们既可以用“地区”,“环境”,“附近学校数量”的数据来预测“房价”,也可以反过来,用“环境”,“附近学校数量”和“房价”来预测“地区”。而回归填补缺失值,正是利用了这种思想。
(2)步骤:
对于一个有n个特征的数据来说,其中特征T有缺失值,我们就把特征T当作标签,其他的n-1个特征和原本的标签组成新的特征矩阵。那对于T来说,它没有缺失的部分,就是我们的Y_test,这部分数据既有标签也有特征,而它缺失的部分,只有特征没有标签,就是我们需要预测的部分。
#用随机森林填补缺失值
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.copy()
#取出第i列
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
print(X_missing_reg)
6、计算均方误差并画出条形图:
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)
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()