欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

人工智能-机器学习-算法-分类算法:决策树与随机森林算法

程序员文章站 2022-07-14 21:00:05
...

一、决策树

1、决策树概念

决策树思想的来源非常朴素,程序设计中的条件分支结构就是if-else结构,最早的决策树就是利用这类结构分割数据的一种分类学习方法。

决策树:

  • 是一种树形结构,本质是一颗由多个判断节点组成的树
  • 其中每个内部节点表示一个属性上的判断,
  • 每个分支代表一个判断结果的输出,
  • 最后每个叶节点代表一种分类结果。

怎么理解这句话?通过一个对话例子
人工智能-机器学习-算法-分类算法:决策树与随机森林算法
上面案例是女生通过定性的主观意识,把年龄放到最上面,那么如果需要对这一过程进行量化,该如何处理呢?
此时需要用到信息论中的知识:信息熵,信息增益

2、信息熵

物理学上,熵 Entropy 是“混乱”程度的量度。系统越有序,熵值越低;系统越混乱或者分散,熵值越高。
信息学上,1948年香农提出了信息熵(Entropy)的概念。

在信息论中,熵(英语:entropy)是接收的每条消息中包含的信息的平均量,又被称为信息熵、信源熵、平均自信息量。这里,“消息”代表来自分布或数据流中的事件、样本或特征。(熵最好理解为不确定性的量度而不是确定性的量度,因为越随机的信源的熵越大)

信息理论:

  1. 信息和消除不确定性是相联系的;
  2. 信息熵越大,信息越不确定,信息熵越小,信息越明确;
  3. 从信息的完整性上进行的描述:当系统的有序状态一致时,数据越集中的地方熵值越小,数据越分散的地方熵值越大;
  4. 从信息的有序性上进行的描述:当数据量一致时,系统越有序,熵值越低;系统越混乱或者分散,熵值越高;

信息熵(information entropy)是度量样本集合纯度最常用的一种指标。

假定当前样本集合 D D D 中第 k k k 类样本所占的比例为 p k p_k pk(k = 1, 2,. . . , |y|) ,

p k = C k C D p_k=\frac{C_k}{C_D} pk=CDCk

C k C_k Ck是按目标值分类后第 k k k 类样本的数量;

C D C_D CD为样本集合D的总数量;

则样本集合 D D D 的信息熵定义为:

E n t ( D ) = − ∑ k = 1 n C k C D l o g 2 C k C D = − ∑ k = 1 n p k l o g 2 p k = − ( p 1 l o g 2 p 1 + p 2 l o g 2 p 2 + . . . + p n l o g 2 p n ) Ent(D) = -\sum_{k=1}^{n}\frac{C_k}{C_D}log_2\frac{C_k}{C_D}=-\sum_{k=1}^{n}p_klog_2{p_k}=-(p_1log_2p_1+p_2log_2p_2+...+p_nlog_2p_n) Ent(D)=k=1nCDCklog2CDCk=k=1npklog2pk=(p1log2p1+p2log2p2+...+pnlog2pn)

其中: E n t ( D ) Ent(D) Ent(D)的值越小,则 样本集合D的纯度越高。单位为“比特”

案例01:
假设我们没有看世界杯的比赛,但是想知道哪支球队会是冠军,
我们只能猜测某支球队是或不是冠军,然后观众用对或不对来回答,
我们想要猜测次数尽可能少,你会用什么方法?
答案:
二分法:
假如有 16 支球队,分别编号,先问是否在 1-8 之间,如果是就继续问是否在 1-4 之间,
以此类推,直到最后判断出冠军球队是哪支。
如果球队数量是 16,我们需要问 4 次来得到最后的答案。那么世界冠军这条消息的信息熵就是 4比特。

那么信息熵等于4,是如何进行计算的呢?

E n t ( D ) = − ( p 1 ∗ l o g 2 p 1 + p 2 ∗ l o g 2 p 2 + . . . + p 1 6 ∗ l o g 2 p 16 ) Ent(D) =-(p_1 * log_2p_1 + p_2 * log_2p_2 + ... + p_16 * log_2p_{16}) Ent(D)=(p1log2p1+p2log2p2+...+p16log2p16)
其中 p 1 p_1 p1, …, p 16 p_{16} p16 分别是这 16 支球队夺冠的概率。
当每支球队夺冠概率相等都是 1 16 \frac{1}{16} 161 的时: E n t ( D ) = − ( 16 ∗ 1 16 ∗ l o g 2 1 16 ) = 4 Ent(D) = -(16 * \frac{1}{16} * log_2\frac{1}{16}) = 4 Ent(D)=(16161log2161)=4
每个事件概率相同时,熵最大,这件事越不确定。

案例02:
篮球比赛里,有4个球队 {A,B,C,D} ,获胜概率分别为{1/2, 1/4, 1/8, 1/8}
求Ent(D)

人工智能-机器学习-算法-分类算法:决策树与随机森林算法

3、决策树分类依据

3.1 信息增益

信息增益:以某特征划分数据集前后的熵的差值。熵可以表示样本集合的不确定性,熵越大,样本的不确定性就越大。因此可以使用划分前后集合熵的差值来衡量使用当前特征对于样本集合D划分效果的好坏。
信息增益:表示得知特征X的信息而使得类Y的信息熵减少的程度的量度。

特征 a a a 对训练数据集 D D D 的信息增益 G a i n ( D , a ) Gain(D,a) Gain(D,a) 定义为:集合 D 的信息熵 H(D) 与特征 a 给定条件下 D 的信息条件熵 H(D|a) 之差,即:信息增益 = entroy(前) - entroy(后)。

  1. G a i n ( D , a ) = E n t ( D ) − E n t ( D ∣ a ) Gain(D,a)=Ent(D)-Ent(D|a) Gain(D,a)=Ent(D)Ent(Da)

  2. E n t ( D ) = − ∑ k = 1 n C k C D l o g 2 C k C D Ent(D) = -\sum_{k=1}^{n}\frac{C_k}{C_D}log_2\frac{C_k}{C_D} Ent(D)=k=1nCDCklog2CDCk

    其中, n n n 表示按目标值分类后的类的总数量 C D C_D CD为集合 D D D 的样本总数量, C k C_k Ck为按目标值分类后第 k k k 类中样本的数量;

  3. E n t ( D ∣ a ) = ∑ k = 1 n C D a k C D E n t ( D a k ) = ∑ k = 1 n C D a k C D [ − ∑ i = 1 m C D a k i C D a k l o g 2 C D a k i C D a k ] = − ∑ k = 1 n C D a k C D [ ∑ i = 1 m C D a k i C D a k l o g 2 C D a k i C D a k ] Ent(D|a) = \sum_{k=1}^n\frac{C_{D_a^k}}{C_D}Ent(D_a^k) = \sum_{k=1}^n\frac{C_{D_a^k}}{C_D}[-\sum_{i=1}^{m}\frac{C^i_{D_a^k}}{C_{D_a^k}}log_2\frac{C^i_{D_a^k}}{C_{D_a^k}}] = -\sum_{k=1}^n\frac{C_{D_a^k}}{C_D}[\sum_{i=1}^{m}\frac{C^i_{D_a^k}}{C_{D_a^k}}log_2\frac{C^i_{D_a^k}}{C_{D_a^k}}] Ent(Da)=k=1nCDCDakEnt(Dak)=k=1nCDCDak[i=1mCDakCDakilog2CDakCDaki]=k=1nCDCDak[i=1mCDakCDakilog2CDakCDaki]

    其中:
    n n n 表示按条件 a a a 的分类后的一级类数量 C D a k C_{D_a^k} CDak 表示集合 D D D 在条件 a a a 的分类条件下,一级类 k k k 中包含的样本数量
    m m m 表示在条件 a a a 的分类条件下,一级类 k k k 中包含的的二级类数量 C D a k i C^i_{D_a^k} CDaki 表示在条件a分类条件下,一级类 k k k 所包含的二级类 i i i 中所包含的样品数量

    即:在条件 a a a 的分类下,分出 a 1 , a 2 , . . . , a k , . . . , a n a_1, a_2, ..., a_k, ..., a_n a1,a2,...,ak,...,an 组,先分别求出这 n n n 组各自的信息熵,然后加权平均得到总的信息熵。

对于特征 a a a b b b c c c 而言,如果 G a i n ( D , a ) > G a i n ( D , b ) > G a i n ( D , c ) Gain(D,a)>Gain(D,b)>Gain(D,c) Gain(D,a)>Gain(D,b)>Gain(D,c),说明这几个特征对于数据集 D D D 的重要性而言 a > b > c a>b>c a>b>c 。在做特征选择或者数据分析的时候,我们应该把特征 a a a 当做第一个分类标准,然后再考虑特征 b b b,最后考虑特征 c c c

3.2 信息增益率

3.2 基尼系数(Gini index)

4、决策树分类算法

名称 分支方式 备注
ID3 信息增益 ID3只能对离散属性的数据集构成决策树
C4.5 信息增益率 优化后解决了ID3分支过程中总喜欢偏向选择值较多的 属性
CART Gini系数 可以进行分类和回归,可以处理离散属性,也可以处理连续属性

比信息增益划分的更加仔细。

5、scikit-learn决策树算法Api

class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None,random_state=None)

  • criterion

    • 特征选择标准
    • “gini"或者"entropy”,前者代表基尼系数,后者代表信息增益。默认"gini",即CART算法。
  • min_samples_split

    • 内部节点再划分所需最小样本数
    • 这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。我之前的一个项目例子,有大概10万样本,建立决策树时,我选择了min_samples_split=10。可以作为参考。
  • min_samples_leaf

    • 叶子节点最少样本数
    • 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。之前的10万样本项目使用min_samples_leaf的值为5,仅供参考。
  • max_depth

    • 决策树最大深度
    • 决策树的最大深度,默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间
  • random_state

    • 随机数种子
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier, export_graphviz


def decision():
    """决策树对泰坦尼克号进行预测生死"""
    # 获取数据
    titanic = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
    print('type(titanic) = ', type(titanic), '----titanic = \n', titanic.head(5))

    # 一、数据处理
    # 1.1 找出特征数据值和目标值
    xDataFrame = titanic[['pclass', 'age', 'sex']]
    ySeries = titanic['survived']
    print('type(xDataFrame) = ', type(xDataFrame), '----特征数据值,xDataFrame = \n', xDataFrame.head(5))
    print('type(ySeries) = ', type(ySeries), '----目标值,ySeries = \n', ySeries.head(5))
    # 缺失值处理
    xDataFrame['age'].fillna(xDataFrame['age'].mean(), inplace=True)

    # 二、特征工程
    # 2.1 分割数据集到训练集合测试集
    xTrainDataFrame, xTestDataFrame, yTrainSeries, yTestSeries = train_test_split(xDataFrame, ySeries, test_size=0.25)
    print('type(xTrainDataFrame) = ', type(xTrainDataFrame), '----xTrainDataFrame = \n', xTrainDataFrame.head(5))
    print('type(xTestDataFrame) = ', type(xTestDataFrame), '----xTestDataFrame = \n', xTestDataFrame.head(5))
    print('type(yTrainSeries) = ', type(yTrainSeries), '----yTrainSeries = \n', yTrainSeries.head(5))
    print('type(yTestSeries) = ', type(yTestSeries), '----yTestSeries = \n', yTestSeries.head(5))
    # 2.2 特征抽取(字典数据类型,当特征值是类别时,进行ont-hot编码)
    dv = DictVectorizer(sparse=False)  # 实例化字典类型数据的特征抽取器(默认值为sparse=True,为True时返回sparse矩阵,当为False时,返回矩阵)
    xTrainDictList = xTrainDataFrame.to_dict(orient="records")  # 将DataFrame格式的xTrain转为Dict字典类型
    xTestDictList = xTestDataFrame.to_dict(orient="records")  # 将DataFrame格式的xTest转为Dict字典类型
    print('type(xTrainDictList) = ', type(xTrainDictList), '----xTrainDictList[0] = \n', xTrainDictList[0])
    xTrainNdArray = dv.fit_transform(xTrainDictList)  # 训练集特征抽取,返回一个ndarray格式的ont-hot编码后的xTrain
    xTestNdArray = dv.transform(xTestDictList);  # 测试集特征抽取
    featureNamesList = dv.get_feature_names()
    print('type(featureNamesList) = ', type(featureNamesList), '----featureNamesList = \n', featureNamesList)
    print('type(xTrainNdArray) = ', type(xTrainNdArray), '----xTrainNdArray = \n', xTrainNdArray)
    print('type(xTestNdArray) = ', type(xTestNdArray), '----xTestNdArray = \n', xTestNdArray)

    # 三、算法工程
    # 3.1 实例化一个决策树估计器对象
    dec_estimator = DecisionTreeClassifier(criterion='gini', max_depth=5)  # 一般使用默认的gini系数,max_depth为决策树层数
    # 3.2 调用fit方法,进行训练
    dec_estimator.fit(xTrainNdArray, yTrainSeries)

    # 四、模型评估
    # 4.1 数据预测,得出预测结果
    predictTestSeries = dec_estimator.predict(xTestNdArray)
    print('type(predictTestSeries) = ', type(predictTestSeries), '----predictTestSeries = \n', predictTestSeries)
    # 4.2 计算准确率
    predictScore = dec_estimator.score(xTestNdArray, yTestSeries)  # 输入”测试集“的特征数据值、目标值
    print('type(predictScore) = ', type(predictScore), '----predictScore = ', predictScore)
    # 4.3 导出决策树的结构文件(dot格式)
    export_graphviz(dec_estimator, out_file="./tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', '女性', '男性'])
    # windows安装graphviz软件,运行命令(dot -Tpng tree.dot -o tree.png)将dot文件转换为pdf、png,如果出现“Format: "png" not recognized. Use one of:”错误提示,则在管理员模式下打开cmd窗口,输入"dot -c",然后再运行命令。
    # http://webgraphviz.com/在线显示图片
    return None

if __name__ == "__main__":
    decision()

dec_estimator = DecisionTreeClassifier(criterion=‘entropy’, max_depth=2)参数下的tree.dot文件转为tree.png图片:

人工智能-机器学习-算法-分类算法:决策树与随机森林算法

dec_estimator = DecisionTreeClassifier(criterion=‘entropy’, max_depth=5)参数下的tree.dot文件转为tree.png图片:

人工智能-机器学习-算法-分类算法:决策树与随机森林算法
dec_estimator = DecisionTreeClassifier(criterion=‘gini’, max_depth=10)参数下的tree.dot文件转为tree.png图片:

人工智能-机器学习-算法-分类算法:决策树与随机森林算法

打印结果:

type(titanic) =  <class 'pandas.core.frame.DataFrame'> ----titanic = 
    row.names pclass  survived   ...        ticket   boat     sex
0          1    1st         1   ...    24160 L221      2  female
1          2    1st         0   ...           NaN    NaN  female
2          3    1st         0   ...           NaN  (135)    male
3          4    1st         0   ...           NaN    NaN  female
4          5    1st         1   ...           NaN     11    male
[5 rows x 11 columns]

type(xDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----特征数据值,xDataFrame = 
   pclass      age     sex
0    1st  29.0000  female
1    1st   2.0000  female
2    1st  30.0000    male
3    1st  25.0000  female
4    1st   0.9167    male

type(ySeries) =  <class 'pandas.core.series.Series'> ----目标值,ySeries = 
 0    1
1    0
2    0
3    0
4    1
Name: survived, dtype: int64

type(xTrainDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----xTrainDataFrame = 
      pclass        age   sex
1128    3rd  31.194181  male
207     1st  31.194181  male
638     3rd  24.000000  male
1202    3rd  31.194181  male
127     1st  25.000000  male

type(xTestDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----xTestDataFrame = 
      pclass        age     sex
258     1st  18.000000  female
1274    3rd  31.194181    male
695     3rd  18.000000  female
10      1st  47.000000    male
220     1st  18.000000  female

type(yTrainSeries) =  <class 'pandas.core.series.Series'> ----yTrainSeries = 
 1128    0
207     1
638     0
1202    0
127     1
Name: survived, dtype: int64
type(yTestSeries) =  <class 'pandas.core.series.Series'> ----yTestSeries = 
 258     1
1274    0
695     0
10      0
220     1
Name: survived, dtype: int64

type(xTrainDictList) =  <class 'list'> ----xTrainDictList[0] = 
 {'pclass': '3rd', 'age': 31.19418104265403, 'sex': 'male'}
 
type(featureNamesList) =  <class 'list'> ----featureNamesList = 
 ['age', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=female', 'sex=male']
 
type(xTrainNdArray) =  <class 'numpy.ndarray'> ----xTrainNdArray = 
 [[31.19418104  0.          0.          1.          0.          1.        ]
 [31.19418104  1.          0.          0.          0.          1.        ]
 [24.          0.          0.          1.          0.          1.        ]
 ...
 [24.          0.          0.          1.          1.          0.        ]
 [11.          0.          0.          1.          1.          0.        ]
 [31.19418104  0.          0.          1.          1.          0.        ]]
 
type(xTestNdArray) =  <class 'numpy.ndarray'> ----xTestNdArray = 
 [[18.          1.          0.          0.          1.          0.        ]
 [31.19418104  0.          0.          1.          0.          1.        ]
 [18.          0.          0.          1.          1.          0.        ]
 ...
 [22.          0.          0.          1.          1.          0.        ]
 [31.19418104  0.          0.          1.          0.          1.        ]
 [31.19418104  0.          0.          1.          0.          1.        ]]
 
type(predictTestSeries) =  <class 'numpy.ndarray'> ----predictTestSeries = 
 [1 0 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
 0 0 1 0 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0
 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 1
 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0
 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0
 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1
 0 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 1 0 1 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 0
 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1
 0 0 1 0 0 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]
 
type(predictScore) =  <class 'numpy.float64'> ----predictScore =  0.8297872340425532

4、决策树算法优缺点

  • 优点:

    • 简单的理解和解释,树木可视化;
    • 需要很少的数据准备,其他技术通常需要数据归一化;
    • 决策树算法可以用于小数据集;
    • 决策树算法的时间复杂度较小,为用于训练决策树的数据点的对数;
    • 对缺失值不敏感。
    • 效率高,决策树只需要一次构建,反复使用,每一次预测的最大计算次数不超过决策树的深度。
  • 缺点:

    • 对连续性的字段比较难预测。
    • 决策树学习者可以创建不能很好地推广数据的过于复杂的树,容易发生过拟合;
    • 当类别太多时,错误可能就会增加的比较快。
    • 忽略了属性之间的相关性,在处理特征关联性比较强的数据时表现得不是太好;
    • 对于各类别样本数量不一致的数据,在决策树当中,信息增益的结果偏向于那些具有更多数值的特征;
  • 改进:

    • 随机森林(集成学习的一种);
    • 减枝cart算法(决策树Api中已经实现),降低过拟合现象;通过DecisionTreeClassifier()方法里的min_samples_leaf参数来调节;如果设定min_samples_leaf=3,那么samples<3的叶子节点会被删除,防止分类太细化,决策树层数过深,产生过拟合。
      人工智能-机器学习-算法-分类算法:决策树与随机森林算法
      注:企业重要决策,由于决策树很好的分析能力,在决策过程应用较多, 可以选择特征

二、随机森林(集成学习方法)

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

随机森林:是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。
数据越复杂,随机森林的优势越明显,因为随机森林估计器中有很多超参数可以进行调优。

1、随机森林建造过程

随机森林中每棵树的建造过程:

  • 用N来表示训练用例(样本)的个数,M表示特征数目。
  • 随机选出m个特征用于决策树,m<<M(m远小于M),m过大容易过拟合。
  • 从N个训练用例(样本)中以有放回抽样的方式,随机取样N次,形成一个训练集(即bootstrap取样),并用未抽到的用例(样本)作预测,评估其误差。

为什么要随机抽样训练集?
如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样的。

为什么要有放回地抽样?
如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是“有偏的”,都是绝对“片面的”(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决。

2、随机森林分类器Api

class sklearn.ensemble.RandomForestClassifier(n_estimators=10, criterion=’gini’, max_depth=None, bootstrap=True, andom_state=None)

  • n_estimators:integer,optional(default = 10) 森林里的树木数量,实践中经验取值为:120,200,300,500,800,1200
  • criteria:string,可选(default =“gini”)分割特征的测量方法,一般使用默认的gini系数,比信息增益(entropy)划分准确一些;
  • max_depth:integer或None,可选(默认=无)树的最大深度
  • bootstrap:boolean,optional(default = True)是否在构建树时使用放回抽样
  • max_features:(default = auto),每个决策树的最大特征数量,
    • max_features=‘auto’:max_features=sqrt(n_features)
    • max_features=‘sqrt’:max_features=sqrt(n_features)
    • max_features=‘log2’:max_features=log2(n_features)
    • None:max_features = n_features
import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.ensemble import RandomForestClassifier


def decision():
    """决策树对泰坦尼克号进行预测生死"""
    # 获取数据
    titanic = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
    print('type(titanic) = ', type(titanic), '----titanic = \n', titanic.head(5))

    # 一、数据处理
    # 1.1 找出特征数据值和目标值
    xDataFrame = titanic[['pclass', 'age', 'sex']]
    ySeries = titanic['survived']
    print('type(xDataFrame) = ', type(xDataFrame), '----特征数据值,xDataFrame = \n', xDataFrame.head(5))
    print('type(ySeries) = ', type(ySeries), '----目标值,ySeries = \n', ySeries.head(5))
    # 缺失值处理
    xDataFrame['age'].fillna(xDataFrame['age'].mean(), inplace=True)

    # 二、特征工程
    # 2.1 分割数据集到训练集合测试集
    xTrainDataFrame, xTestDataFrame, yTrainSeries, yTestSeries = train_test_split(xDataFrame, ySeries, test_size=0.25)
    print('type(xTrainDataFrame) = ', type(xTrainDataFrame), '----xTrainDataFrame = \n', xTrainDataFrame.head(5))
    print('type(xTestDataFrame) = ', type(xTestDataFrame), '----xTestDataFrame = \n', xTestDataFrame.head(5))
    print('type(yTrainSeries) = ', type(yTrainSeries), '----yTrainSeries = \n', yTrainSeries.head(5))
    print('type(yTestSeries) = ', type(yTestSeries), '----yTestSeries = \n', yTestSeries.head(5))
    # 2.2 特征抽取(字典数据类型,当特征值是类别时,进行ont-hot编码)
    dv = DictVectorizer(sparse=False)  # 实例化字典类型数据的特征抽取器(默认值为sparse=True,为True时返回sparse矩阵,当为False时,返回矩阵)
    xTrainDictList = xTrainDataFrame.to_dict(orient="records")  # 将DataFrame格式的xTrain转为Dict字典类型
    xTestDictList = xTestDataFrame.to_dict(orient="records")  # 将DataFrame格式的xTest转为Dict字典类型
    print('type(xTrainDictList) = ', type(xTrainDictList), '----xTrainDictList[0] = \n', xTrainDictList[0])
    xTrainNdArray = dv.fit_transform(xTrainDictList)  # 训练集特征抽取,返回一个ndarray格式的ont-hot编码后的xTrain
    xTestNdArray = dv.transform(xTestDictList);  # 测试集特征抽取
    featureNamesList = dv.get_feature_names()
    print('type(featureNamesList) = ', type(featureNamesList), '----featureNamesList = \n', featureNamesList)
    print('type(xTrainNdArray) = ', type(xTrainNdArray), '----xTrainNdArray = \n', xTrainNdArray)
    print('type(xTestNdArray) = ', type(xTestNdArray), '----xTestNdArray = \n', xTestNdArray)

    # 三、算法工程(决策树)
    # # 3.1 实例化一个决策树估计器对象
    # dec_estimator = DecisionTreeClassifier(criterion='entropy', max_depth=2)  # 默认使用gini系数,或采用“entropy”信息增益,max_depth为决策树层数
    # # 3.2 调用fit方法,进行训练
    # dec_estimator.fit(xTrainNdArray, yTrainSeries)
    #
    # # 四、模型评估
    # # 4.1 数据预测,得出预测结果
    # predictTestSeries = dec_estimator.predict(xTestNdArray)
    # # 4.2 计算准确率
    # predictScore = dec_estimator.score(xTestNdArray, yTestSeries)  # 输入”测试集“的特征数据值、目标值
    # # 4.3 导出决策树的结构文件(dot格式)
    # export_graphviz(dec_estimator, out_file="./tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', '女性', '男性'])
    # # windows安装graphviz软件,运行命令(dot -Tpng tree.dot -o tree.png)将dot文件转换为pdf、png,如果出现“Format: "png" not recognized. Use one of:”错误提示,则在管理员模式下打开cmd窗口,输入"dot -c",然后再运行命令。

    # 三、算法工程(随机森林)
    # 3.1 实例化一个随机森林估计器对象(随机森林无法导出决策树的结构文件)
    rf = RandomForestClassifier()
    # 3.2 网格搜索进行超参数调优,构造一些参数的值进行搜索
    param = {"n_estimators": [120, 200, 300, 500, 800, 1200], "max_depth": [5, 8, 15, 25, 30]}
    # 网格搜索与交叉验证
    gc = GridSearchCV(rf, param_grid=param, cv=2)
    gc.fit(xTrainNdArray, yTrainSeries)

    # 四、模型评估
    predictTestSeries = gc.predict(xTestNdArray)
    scoreTest = gc.score(xTestNdArray, yTestSeries)
    print("在测试集上的预测结果,predictTestSeries =\n", predictTestSeries)
    print("在测试集上准确率,scoreTest = ", scoreTest)
    print("查看选择的参数模型:", gc.best_params_)
    return None


if __name__ == "__main__":
    decision()

打印结果:

type(titanic) =  <class 'pandas.core.frame.DataFrame'> ----titanic = 
    row.names pclass  survived   ...        ticket   boat     sex
0          1    1st         1   ...    24160 L221      2  female
1          2    1st         0   ...           NaN    NaN  female
2          3    1st         0   ...           NaN  (135)    male
3          4    1st         0   ...           NaN    NaN  female
4          5    1st         1   ...           NaN     11    male
[5 rows x 11 columns]

type(xDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----特征数据值,xDataFrame = 
   pclass      age     sex
0    1st  29.0000  female
1    1st   2.0000  female
2    1st  30.0000    male
3    1st  25.0000  female
4    1st   0.9167    male

type(ySeries) =  <class 'pandas.core.series.Series'> ----目标值,ySeries = 
 0    1
1    0
2    0
3    0
4    1
Name: survived, dtype: int64

type(xTrainDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----xTrainDataFrame = 
      pclass        age   sex
213     1st  31.194181  male
1243    3rd  31.194181  male
108     1st  44.000000  male
254     1st  61.000000  male
1198    3rd  31.194181  male

type(xTestDataFrame) =  <class 'pandas.core.frame.DataFrame'> ----xTestDataFrame = 
      pclass        age     sex
836     3rd  37.000000    male
1290    3rd  31.194181    male
1233    3rd  31.194181  female
892     3rd  31.194181    male
62      1st  31.194181    male

type(yTrainSeries) =  <class 'pandas.core.series.Series'> ----yTrainSeries = 
 213     0
1243    0
108     1
254     0
1198    0
Name: survived, dtype: int64

type(yTestSeries) =  <class 'pandas.core.series.Series'> ----yTestSeries = 
 836     0
1290    0
1233    0
892     0
62      0
Name: survived, dtype: int64

type(xTrainDictList) =  <class 'list'> ----xTrainDictList[0] = 
 {'pclass': '1st', 'age': 31.19418104265403, 'sex': 'male'}
 
type(featureNamesList) =  <class 'list'> ----featureNamesList = 
 ['age', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=female', 'sex=male']
 
type(xTrainNdArray) =  <class 'numpy.ndarray'> ----xTrainNdArray = 
 [[31.19418104  1.          0.          0.          0.          1.        ]
 [31.19418104  0.          0.          1.          0.          1.        ]
 [44.          1.          0.          0.          0.          1.        ]
 ...
 [31.19418104  0.          0.          1.          0.          1.        ]
 [31.19418104  0.          0.          1.          1.          0.        ]
 [64.          1.          0.          0.          1.          0.        ]]
 
type(xTestNdArray) =  <class 'numpy.ndarray'> ----xTestNdArray = 
 [[37.          0.          0.          1.          0.          1.        ]
 [31.19418104  0.          0.          1.          0.          1.        ]
 [31.19418104  0.          0.          1.          1.          0.        ]
 ...
 [31.19418104  0.          0.          1.          0.          1.        ]
 [26.          0.          0.          1.          0.          1.        ]
 [ 8.          0.          1.          0.          1.          0.        ]]
 
在测试集上的预测结果,predictTestSeries =
 [0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1
 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 0 1
 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
 1 0 0 1 0 0 0 1 0 1 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
 0 0 1 1 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1
 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0
 1 0 1 0 0 1 0 0 0 1 1 0 1 1 1 0 0 0 1 0 0 0 1 1 0 1 1 1 0 1 0 0 1]
 
在测试集上准确率,scoreTest =  0.8237082066869301

查看选择的参数模型: {'max_depth': 5, 'n_estimators': 300}

3、随机森林的优缺点

3.1 随机森林的优点

  • 在当前所有算法中,具有极好的准确率;
  • 能够有效地运行在大数据集上(“大”体现在样本数、特征数);
  • 能够处理具有高维特征的输入样本,而且不需要降维
  • 能够评估各个特征在分类问题上的重要性;
  • 对于缺省值问题也能够获得很好得结果;
  • 随机森林是使用最多的一种机器学习算法

3.2 随机森林的缺点

超参数调优,找不到合适的参数组合来调优。