集成算法概述
集成学习是通过在数据上构建多个模型,集成所有的模型的结果。常用的有随机森林、梯度提升树、Xgboost等。其目标是考虑多个评估器的建模结果,汇总后得到一个综合结果,以此来获取比单个模型更好的回归或分类表现。
多个模型集成成为的模型叫做集成评估器,组成集成评估器的每个模型都叫做基评估器,通常有三类集成算法:袋装法(Bagging),提升法(Boosting),和Stacking。
- 袋装法:构建多个相互独立的评估器,然后对其预测进行平均或多数表决原则来决定集成评估器的结果。袋装法的结果就是随机森林。
- 提升法:基评估器是相关的,是按顺序一一构建的。核心是结合弱评估器的力量一次次对难以评估的样本进行预测,从而构成一个强评估器。提升法的代表模型有Adaboost和梯度提升树。
sklearn中集成算法模块ensemble
ensemble模块提供了多种集成算法,具体如下:
随机森林
随机森林分类器RandomForestClassifier
- 基评估器参数
参数 | 含义 |
criterion | 不纯度的衡量指标,有基尼系数和信息熵 |
max_depth | 树的最大深度,超过最大深度的树枝都会被剪掉 |
min_samples_leaf | 一个节点在分支后的每个节点都必须至少包含min_samples_leaf个训练样本,否则分枝不会发生 |
min_samples_split | 一个节点必须至少包含min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生 |
max_features | max_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃,默认值是总特征个数开平方取整。 |
min_impurity_decrease | 限制信息增益的大小,信息增益小于设定数值的分枝不会发生 |
- n_estimators
这是森林中的树的数量,即基评估器的数量。一般n_entimators越大,模型的效果往往越好,但是达到一定程度后,随机森林的精确性往往不再上升或开始波动,并且,参数越大需要的内存和计算量也越大,训练时间越长。因此实际中需要考虑多方面的因素进行平衡。
n_estimators学习曲线示例:
supera = []
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()
supera.append(rfc_s)
print(max(supera), supera.index(max(supera)))
plt.plot(range(1,201), supera)
plt.show()
- random_state
决策树中的这个参数控制决策树生成时分枝的选择,决策树生成时是从最重要的属性中随机选择一个进行划分,由random_state控制。而在随机森林中,这个参数控制随机森林生成的模式,而非随机森林的一棵树。我们可以观察到,当random_state固定时,随机森林中生成是一组固定的树,但每棵树依然是不一致的,这是用”随机挑选特征进行分枝“的方法得到的随机性。并且我们可以证明,当这种随机性越大的时候,袋装法的效果一般会越来越好。用袋装法集成时,基分类器应当是相互独立的,是不相同的。
但这种做法的局限性是很强的,当我们需要成千上万棵树的时候,数据不一定能够提供成千上万的特征来让我们构筑尽量多尽量不同的树。因此,除了random_state。我们还需要其他的随机性。 - bootstrap 和 oob_score
为了让基分类器尽量不同,可以使用不同的训练集进行训练,就可以用有放回的随机抽样方法形成不同的训练数据(这西瓜书里也有。。。。又忘了),bootstrap参数就是用来控制抽样技术的参数。
bootstrap默认为true,代表采用有放回的随机抽样计数。
这样得到的数据集并不会包含所有的样本数据,一般大约有63%的样本会被选到,因此,就可以将没有被选到的样本作为测试集使用。也就是说,在使用随机森林时,可以不划分测试机和训练集,只需要用袋外的数据来测试我们的模型即可,这就需要将参数obb_score调整为True,训练完成后,可以用随机森林的属性obb_score来查看我们的在袋外数据上测试的结果。
rfc = RandomForestClassifier(n_estimators=25,oob_score=True)
rfc.fit(wine.data, wine.target)
rfc.oob_score_
- 其他常用属性和接口
# 属性的重要性
rfc.feature_importances_
# 返回样本分类结果
rfc.predict(Xtest)
# 样本被分到每一类标签的概率
rfc.predict_proba(Xtest)
# 返回每个测试样本所在的叶子节点的索引
rfc.apply(Xtest)
随机森林回归器——RandomForestRrgressor
skelen.ensemble.RandomForestRegressor
重要参数,属性与接口
- criterion
和决策回归树一样,回归树的衡量分枝的指标,支持的标准有三种:
1)输入“mse”使用均方误差(mean squared error),父节点和子节点之间的均方误差的差额来作为特征选择的标准,通过使用叶子节点的均值来最小化L2损失。
2)输入"friedman_mse"使用费尔德曼均方误差,这种指标使用费尔德曼针对潜在分支中的问题改进后的均方误差。
3)输入"mae" 使用绝对平方误差,使用节点的中值来最小化L1损失
其他属性也包括feature_importances_,接口有apply,fit,predict,score等核心的。
在回归树中MSE既是分支质量的衡量标准也是回归树回归质量的标准,在回归中,MSE越小越好,而接口score返回的是R2,R2定义是:
,其中y-hat是所有标签的平均值。
随机森林回归器的参数,接口等与随机森林分类器的基本一样,但没有predict_proba()这个方法。
cross_val_score(regressor, boston.data, boston.target, cv=10, scoring="neg_mean_squared_error")
# 交叉验证的评估指标scoring
# sklearn中的模型评估指标(打分)的列表
sorted(sklearn.metrics.SCORERS.keys())
# 可以输出所有的评估指标
随机森林回归填补缺失值
可以使用sklearn.impute.SimpleImputer 来填补缺失值。
具体操作为:
from sklearn.impute import SampleImputer
# 实例化
# imp = SampleImputer(missing_values=np.nan, strategy='constant', fill_value=0),填补0
imp = SampleImputer(missing_values=np.nan, strategy='mean')
# 返回填补后的特征矩阵
missing_val = imp.fit_transform(X_missing)
随机森林算法填补缺失值
随机森林回归的目标是预测数据的结果,对于有缺失值的特征,我们可以直接将该特征当作标签,其他的n-1个特征和原本的标签组成新的特征矩阵,对于有缺失值的特征,它没有缺失值的部分就是新的Y_test,也就是说特征T不缺失的部分对应的其他n-1个特征加上本来的标签构成了X_train,特征T没有确实的值作为Y_test,而特征T缺失的部分对应的构成测试集。
如果有多个特征存在缺失值,则先选择缺失最少的进行填补。填补一个特征的缺失值时,先将其他特征的缺失值用0代替。
基本操作:
X_missing_reg = X_missing.copy() #缺失数据集
# argsort()带索引的排序,返回从小到大的顺序所对应的索引
sortindex = np.argsort(X_missing_reg.isnull().sum(axis=0)).values
# 构建新的特质矩阵和新的标签
for i in sortindex:
# 每次将旧的缺失数据集复制到一个临时变量中
df = X_missing_reg
# 分离出第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)
# 构建新的train和test
Y_train = fillc[fillc.notnull()]
Y_test = fillc[fillc.isnull()]
# Y对应行的所有列
X_train = df_0[Y_train.index,:]
X_test = df_0[Y_test.index,:]
# 实例化模型
rfc = RandomForestRegressor(n_estimators=100)
rfc = rfc.fit(X_train, Y_train)
# 预测
Y_pre = rfc.predict(X_test)
# 取出i列缺失值的行和i列更新,loc就是location,而iloc只能接受整数
X_missing_reg.loc[X_missing_reg.iloc[:,i].isnull(), i] = Y_pre