avatar


10.集成学习和随机森林

集成学习

江南七怪
金庸的武侠小说《射雕英雄传》中有一个组合,叫江南七怪。论单兵作战能力,这七人水平都一般。但是倘若七人联手,虽说不是天下第一,也是有一定的江湖地位。
集成学习就和这个类似。

集成学习通过建立几个模型来解决单一预测问题。
它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测,这些预测最后结合成组合预测。

《集成学习概览及其Python实现:2.GBDT》中,我们对上面的那段话有更更翔实的论述。

随机森林

随机森林是由多颗决策树组成的集成学习分类器,最后输出的类别是由每一颗树输出类别的众数而定,即由所有的树来进行投票。
《经典机器学习及其Python实现:6.kNN》中,我们讨论的kNN也是众数投票的思想。

但需要注意的是由多颗决策树组成的集成学习分类器不一定是随机森林,在《集成学习概览及其Python实现:2.GBDT》中,我们会看到更多的方法。Adaboost、GBDT都是由多颗决策树组成的,但都不是随机森林。在《集成学习概览及其Python实现:3.XGBoost》中XGBoost,甚至可以不由决策树组成。

随机森林的建立过程

假设现在有N个样本,M个特征。

我们以一棵树的建立过程为例

  1. 随机在N个样本中选择n个样本,n<Nn < N
    1. 随机有放回抽样,所以不同的批次之间可能有重复样本。
  2. 随机在M个特征中选出m个特征,m<Mm < M

通过这种方法,循环往复,就可以得到森林了。

所以,多棵决策树,样本,特征都大多不一样,所以每棵决策树的分类结果都不太一样。
随机有放回抽样,这种抽样方法有一个时髦的名字,bootstrap

为什么要随机抽样训练集?
如果不进行随机抽样,那么每棵树的训练集都是一样的,最后分类结果当然也是一样的。
那么,这样,投票还有什么意义呢?

为什么要有放回的抽样?
如果不是有放回的抽样,那么每棵树的训练集都是不一样的,没有交集。这样每棵树都是’有偏的’。每棵树的训练结果也都有很大的差异。
那么,这样,还投什么票呢?大家意见都不一致,就没有多数票。

随机森林的实现

1
from sklearn.ensemble import RandomForestClassifier

参数:

  • n_estimators:森林里的最多有多少颗树,默认10
  • criteria:分割特征的测量方法,默认基尼
  • max_depth:树的最大深度,默认无限
  • max_features:每棵决策树的最大特征数量,又这么几种取值
    • auto:m_features\sqrt{m\_features},默认auto
    • sqrt:m_features\sqrt{m\_features},和auto等效
    • log2:log2m_features\log_2 m\_features
    • None:max_features=m_featuresmax\_features = m\_features
  • bootstrap:是否在构建树时使用放回抽样,默认True,即有放回抽样。

所以,随机森林的超参数包括

  1. n_estimators:决策树的数量
  2. max_depth:每棵树的深度

我们对这两个参数进行网格搜索

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
import pandas as pd

# 获取数据
titan = pd.read_csv('http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt')

# 处理数据
x = titan[['pclass','age','sex',]]

# 缺失值处理
x['age'].fillna(x['age'].mean(),inplace=True)

y = titan['survived']

# 分割数据到训练集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)

# 特征工程
# 类别用 One-Hot编码
dict = DictVectorizer(sparse=False)
# to_dict
x_train = dict.fit_transform(x_train.to_dict(orient='records'))
print(dict.get_feature_names())
x_test = dict.transform(x_test.to_dict(orient='records'))

rf = RandomForestClassifier()
# 网格搜索与交叉验证

gc = GridSearchCV(rf,param_grid={'n_estimators':[120,200,300,500,800,1200],'max_depth':[2,4,8,16,32]},cv=10)

gc.fit(x_train,y_train)

print('准确率有')
print(gc.score(x_test,y_test))

print('最佳模型')
print(gc.best_estimator_)
print(gc.best_score_)

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
['age', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=female', 'sex=male']
准确率有
0.8601823708206687
最佳模型
RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,
criterion='gini', max_depth=4, max_features='auto',
max_leaf_nodes=None, max_samples=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=300,
n_jobs=None, oob_score=False, random_state=None,
verbose=0, warm_start=False)
0.80995670995671

随机森林的优缺点

  1. 优点

    1. 具有较好的准确率
    2. 在大数据集上效率较好
    3. 能够处理具有高维特征的输入样本,不需要降维
    4. 能够评估各个特征在分类问题上的重要性
  2. 缺点

    1. 训练时间长
文章作者: Kaka Wan Yifan
文章链接: https://kakawanyifan.com/10210
版权声明: 本博客所有文章版权为文章作者所有,未经书面许可,任何机构和个人不得以任何形式转载、摘编或复制。

评论区