• 【Python人工智能】Python全栈体系(十七)


    人工智能

    第五章 车辆评级分类与cart分类树

    一、决策树分类

    1. 算法核心原理

    • 决策树的核心思想:相似的输入产生相似的输出。

    2. 决策树的关键问题

    • 这么多特征,使用哪个特征先进行子表划分?

    3. CART 分类树

    • CART 分类树算法对每个特征进行二分,寻找分割点时使用基尼系数来表达数据集的不纯度,基尼系数越小,不纯度越低,数据集划分的效果越好。
    • CART 分类树划分子表的过程:
      • 针对每个特征,基于基尼系数计算最优分割值。在计算出来的各个特征的每个分割值对数据集 D D D的基尼系数中,选择基尼系数最小的特征A和对应的分割值a。根据这个最优特征和最优分割值,把数据集划分成两部分 D 1 D_1 D1 D 2 D_2 D2,同时建立当前节点的左右节点,左节点的数据集 D D D D 1 D_1 D1,右节点的数据集 D D D D 2 D_2 D2.对左右节点的子节点递归调用这个过程,生成决策树。
    • 而 CART 分类树也基于基尼系数来决定子表划分所选特征的次序

    4. 基尼系数

    • 对于样本D,个数为|D|,假设K个类别,第k个类别的数量为 C k C_k Ck,则样本D的基尼系数表达式:
      G i n i ( D ) = 1 − ∑ i = 1 K ( ∣ C k ∣ ∣ D ∣ ) 2 Gini(D) = 1 - \sum_{i=1}^K \left(\frac{|C_k|}{|D|}\right)^2 Gini(D)=1i=1K(DCk)2
    • 有100个样本( D 1 D_1 D1)包含A与B两个类别,数量分别为40与60,Gini( D 1 D_1 D1) = ?
      1 − ( ( ∣ 40 ∣ ∣ 100 ∣ ) 2 + ( ∣ 60 ∣ ∣ 100 ∣ ) 2 ) = 1 − ( 0.16 + 0.36 ) = 0.48 1 - \left( \left(\frac{|40|}{|100|}\right)^2 + \left( \frac{|60|}{|100|}\right)^2 \right) = 1 - (0.16 + 0.36) = 0.48 1((10040)2+(10060)2)=1(0.16+0.36)=0.48
    • 有100个样本( D 2 D_2 D2)包含A与B两个类别,数量分别为10与90,Gini( D 2 D_2 D2) = ?
      1 − ( ( ∣ 10 ∣ ∣ 100 ∣ ) 2 + ( ∣ 90 ∣ ∣ 100 ∣ ) 2 ) = 1 − ( 0.01 + 0.81 ) = 0.18 1 - \left( \left( \frac{|10|}{|100|}\right)^2 + \left( \frac{|90|}{|100|}\right)^2 \right) = 1 - (0.01 + 0.81) = 0.18 1((10010)2+(10090)2)=1(0.01+0.81)=0.18
    • 对于样本D,个数为|D|,根据特征A的某个值a,把D分成 D 1 D_1 D1 D 2 D_2 D2,则在特征A的条件下,样本D的基尼系数表达式为:
      G i n i ( D , A ) = ∣ D 1 ∣ ∣ D ∣ G i n i ( D 1 ) + ∣ D 2 ∣ ∣ D ∣ G i n i ( D 2 ) Gini(D,A) = \frac{|D_1|}{|D|} Gini(D_1) + \frac{|D_2|}{|D|} Gini(D_2) Gini(D,A)=DD1Gini(D1)+DD2Gini(D2)

    5. 决策树的生成过程

    • 算法输入训练集D,基尼系数的阈值,样本个数阈值。输出决策树T。
      • 对于当前节点的数据集为D,如果样本个数小于阈值,则返回决策子树,当前节点停止递归。
      • 计算样本集D的基尼系数,如果基尼系数小于阈值,则返回决策树子树,当前节点停止递归。
      • 计算当前节点现有的各个特征的各个特征值对数据集D的基尼系数。
      • 在计算出来的各个特征的各个特征值对数据集D的基尼系数中,选择基尼系数最小的特征A和对应的特征值a。根据这个最优特征和最优特征值,把数据集划分成两部分 D 1 D_1 D1 D 2 D_2 D2,同时建立当前节点的左右节点,左节点的数据集D为 D 1 D_1 D1,右节点的数据集D为 D 2 D_2 D2
      • 对左右的子节点递归的调用1-4步,生成决策树。
    • 预测过程:对生成的决策树做预测的时候,假如测试集里的样本A落到了某个叶子节点,而节点里有多个训练样本。则对于A的类别预测采用的是这个叶子节点里概率最大的类别

    6. 决策树分类实现

    • 决策树分类器模型相关 API:
    import sklearn.tree as st
    
    # 决策树分类器
    model = st.DecisionTreeClassifier(
    		max_depth=6, min_samples_split=3, random_state=7)
    model.fit(train_x, train_y)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    7. 鸢尾花案例

    import sklearn.tree as st
    model = st.DecisionTreeClassifier(max_depth=4, min_samples_split=3)
    model.fit(train_x, train_y)
    # 评估 模型准确率
    pred_test_y = model.predict(test_x)
    print((pred_test_y==test_y).sum() / test_y.size)
    print(test_y.values)
    """
    0.8666666666666667
    [2 0 0 1 0 2 2 2 1 1 2 1 1 0 0]
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    8. 集合模型分类实现

    • 集合模型提供的常用分类器
    import sklearn.ensemble as se
    
    model = se.RandomForestClassifier(...) # 随机森林分类器
    model = se.AdaBoostClassifier(...) # AdaBoost分类器
    model = se.GridientBoostingClassifier(...) # GBDT分类器
    
    • 1
    • 2
    • 3
    • 4
    • 5

    二、预测小汽车等级

    • car.txt 样本文件中统计了小汽车的常见特征信息及小汽车的分类,使用这些数据基于决策树分类算法训练模型预测小汽车等级。
    • 汽车价格 维修费用 车门数量 载客数 后备箱 安全性 汽车级别
    • 分析实现思路:
      • 加载数据。
      • 特征分析与特征工程。
      • 数据预处理(标签编码)。
      • 训练模型。
      • 模型测试。
    import numpy as np
    import pandas as pd
    
    data = pd.read_csv('car.txt', header=None) # 不想把第一行当做表头
    data.head()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    请添加图片描述

    data[0].value_counts() # 汽车价格分成4类,按类别划分每个类别有432个样本
    """
    vhigh    432
    low      432
    med      432
    high     432
    Name: 0, dtype: int64
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 确定:是分类问题,还是回归问题?答:分类
    • 选哪一个分类模型:逻辑回归、决策树、RF、GBDT、AdaBoost?答:RF(当然也可以尝试其他模型)
    # 针对当前这组数据完成标签编码预处理
    import sklearn.preprocessing as sp
    
    # 遍历每一列数据
    train_data = pd.DataFrame([])
    encoders = {}
    for col_ind, col_val in data.items():
        encoder = sp.LabelEncoder()
        train_data[col_ind] = encoder.fit_transform(col_val)
        encoders[col_ind] = encoder
    train_data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    请添加图片描述

    # 整理输入集与输出集
    x, y = train_data.iloc[:, :-1], train_data[6]
    x.shape, y.shape
    """
    ((1728, 6), (1728,))
    """
    # 创建分类模型
    model = se.RandomForestClassifier(max_depth=6, n_estimators=400, random_state=7)
    # 做5次交叉验证,验证一下这个模型是否可用
    scores = ms.cross_val_score(model, x, y, cv=5, scoring='f1_weighted')
    # 如果分数还可以,再正儿八经的训练模型
    print(scores.mean())
    """
    0.7537201013972693
    """
    
    # 模型评估(先用训练样本进行模型评估)
    model.fit(x, y)
    pred_y = model.predict(x)
    print(sm.classification_report(y, pred_y))
    print(sm.confusion_matrix(y,pred_y)) # 把1类别的全归到0类别里了
    """
                  precision    recall  f1-score   support
    
               0       0.77      0.82      0.79       384
               1       0.00      0.00      0.00        69
               2       0.95      0.99      0.97      1210
               3       1.00      0.77      0.87        65
    
        accuracy                           0.91      1728
       macro avg       0.68      0.65      0.66      1728
    weighted avg       0.87      0.91      0.89      1728
    
    [[ 315    0   69    0]
     [  69    0    0    0]
     [  11    0 1199    0]
     [  15    0    0   50]]
    """
    
    data = [
        ['high', 'med', '5more', '4', 'big', 'low', 'unacc'],
        ['high', 'high', '4', '4', 'med', 'med', 'acc'],
        ['low', 'low', '2', '4', 'small', 'high', 'good'],
        ['low', 'med', '3', '4', 'med', 'high', 'vgood']
    ]
    test_data = pd.DataFrame(data)
    for col_ind, col_val in test_data.items():
        encoder = encoders[col_ind]
        encoded_col = encoder.transform(col_val)
        test_data[col_ind] = encoded_col
    # 整理输入集与输出集
    test_x, test_y = test_data.iloc[:,:-1], test_data[6]
    pred_test_y = model.predict(test_x)
    pred_test_y
    """
    array([2, 0, 0, 0])
    """
    encoders[6].inverse_transform(pred_test_y)
    """
    array(['unacc', 'acc', 'acc', 'acc'], dtype=object)
    """
    
    • 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
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    三、验证曲线与学习曲线

    1. 验证曲线

    • 验证曲线描述的关系即是模型性能关于模型超参数的函数关系:
      • 模型性能 = f(超参数)

    2. 验证曲线实现

    • sklearn 提供的验证曲线 API:
    train_scores, test_scores = ms.validation_curve(
    	model,  # 模型
        输入集, 输出集,
        'n_estimators',  # 超参数名
        np.arange(50, 550, 50),	# 超参数序列
        cv=5	# 折叠数
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 返回train_scores与test_scores为每个超参数取值下的每次交叉验证结果组成的得分矩阵。

    3. 案例:预测小汽车等级调整参数

    import numpy as np
    import pandas as pd
    
    data = pd.read_csv('car.txt', header=None) # 不想把第一行当做表头
    
    # 针对当前这组数据完成标签编码预处理
    import sklearn.preprocessing as sp
    import sklearn.ensemble as se
    import sklearn.model_selection as ms
    import sklearn.metrics as sm
    # 遍历每一列数据
    train_data = pd.DataFrame([])
    encoders = {}
    for col_ind, col_val in data.items():
        encoder = sp.LabelEncoder()
        train_data[col_ind] = encoder.fit_transform(col_val)
        encoders[col_ind] = encoder
        
    # 整理输入集与输出集
    x, y = train_data.iloc[:, :-1], train_data[6]
    # 创建分类模型(调参之后设定的参数值)
    model = se.RandomForestClassifier(max_depth=9, n_estimators=140, random_state=7)
    
    # 验证曲线,选取最优超参数
    import matplotlib.pyplot as plt
    # params =  np.arange(50, 550, 50)
    params = np.arange(100, 200, 10)
    train_scores, test_scores = ms.validation_curve(model, x, y, param_name='n_estimators', param_range=params, cv=5)
    scores = test_scores.mean(axis=1)
    # 验证曲线可视化
    plt.grid(linestyle=':')
    plt.plot(params, scores, 'o-', color='dodgerblue', label='n_estimators VC')
    plt.legend()
    
    • 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

    请添加图片描述

    # 调整max_depth
    params = np.arange(1, 12)
    train_scores, test_scores = ms.validation_curve(model, x, y, param_name='max_depth', param_range=params, cv=5)
    scores = test_scores.mean(axis=1)
    # 验证曲线可视化
    plt.grid(linestyle=':')
    plt.plot(params, scores, 'o-', color='orangered', label='max_depth VC')
    plt.legend()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    请添加图片描述

    model.fit(x, y)
    pred_y = model.predict(x)
    print(sm.classification_report(y, pred_y))
    print(sm.confusion_matrix(y,pred_y))
    """
                  precision    recall  f1-score   support
    
               0       0.96      1.00      0.98       384
               1       1.00      0.75      0.86        69
               2       1.00      1.00      1.00      1210
               3       0.94      1.00      0.97        65
    
        accuracy                           0.99      1728
       macro avg       0.97      0.94      0.95      1728
    weighted avg       0.99      0.99      0.99      1728
    
    [[ 383    0    0    1]
     [  14   52    0    3]
     [   3    0 1207    0]
     [   0    0    0   65]]
     """
    data = [
        ['high', 'med', '5more', '4', 'big', 'low', 'unacc'],
        ['high', 'high', '4', '4', 'med', 'med', 'acc'],
        ['low', 'low', '2', '4', 'small', 'high', 'good'],
        ['low', 'med', '3', '4', 'med', 'high', 'vgood']
    ]
    test_data = pd.DataFrame(data)
    for col_ind, col_val in test_data.items():
        encoder = encoders[col_ind]
        encoded_col = encoder.transform(col_val)
        test_data[col_ind] = encoded_col
    # 整理输入集与输出集
    test_x, test_y = test_data.iloc[:,:-1], test_data[6]
    pred_test_y = model.predict(test_x)
    encoders[6].inverse_transform(pred_test_y)
    """
    array(['unacc', 'acc', 'good', 'vgood'], dtype=object)
    """
    
    • 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

    4. 学习曲线

    • 学习曲线描述的关系即是模型性能关于训练样本量大小的函数关系:
      • 模型性能 = f(训练集大小)

    5. 学习曲线实现

    • sklearn 提供的学习曲线 API:
    train_scores, test_scores = ms.learning_curve(
    	model,  # 模型
        输入集, 输出集,
        train_sizes=[0.9, 0.8, 0.7],	# 训练集大小序列
        cv=5	# 折叠数
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 返回train_scores与test_scores为每个超参数取值下的每次交叉验证结果组成的得分矩阵。

    6. 案例:预测小汽车等级调整参数

    params = np.arange(0.1, 1.1, 0.1)
    _, train_scores, test_scores = ms.learning_curve(model, x, y, train_sizes=params, cv=5)
    scores = test_scores.mean(axis = 1)
    
    # 学习曲线可视化
    plt.grid(linestyle=':')
    plt.plot(params, scores, 'o-', color='green', label='Learning Curve')
    plt.legend()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    请添加图片描述

    四、完整案例

    import numpy as np
    import pandas as pd
    
    data = pd.read_csv('car.txt', header=None) # 不想把第一行当做表头
    data.head()
    
    """
    	0		1		2	3	4		5		6
    0	vhigh	vhigh	2	2	small	low		unacc
    1	vhigh	vhigh	2	2	small	med		unacc
    2	vhigh	vhigh	2	2	small	high	unacc
    3	vhigh	vhigh	2	2	med		low		unacc
    4	vhigh	vhigh	2	2	med		med		unacc
    """
    
    # 确定:是分类问题,还是回归问题? 分类
    #  选哪一个分类模型:逻辑回归、决策树、RF、GBDT、AdaBoost? RF
    
    # 针对当前这组数据完成标签编码预处理
    import sklearn.preprocessing as sp
    import sklearn.ensemble as se
    import sklearn.model_selection as ms
    import sklearn.metrics as sm
    # 遍历每一列数据
    train_data = pd.DataFrame([])
    encoders = {}
    for col_ind, col_val in data.items():
        encoder = sp.LabelEncoder()
        train_data[col_ind] = encoder.fit_transform(col_val)
        encoders[col_ind] = encoder
        
    # 整理输入集与输出集
    x, y = train_data.iloc[:, :-1], train_data[6]
    # 创建分类模型
    model = se.RandomForestClassifier(max_depth=9, n_estimators=140, random_state=7)
    
    # 验证曲线,选取最优超参数
    import matplotlib.pyplot as plt
    # params =  np.arange(50, 550, 50)
    params = np.arange(100, 200, 10)
    train_scores, test_scores = ms.validation_curve(model, x, y, param_name='n_estimators', param_range=params, cv=5)
    scores = test_scores.mean(axis=1)
    # 验证曲线可视化
    plt.grid(linestyle=':')
    plt.plot(params, scores, 'o-', color='dodgerblue', label='n_estimators VC')
    plt.legend()
    
    • 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
    • 42
    • 43
    • 44
    • 45
    • 46

    请添加图片描述

    # 调整max_depth
    params = np.arange(1, 12)
    train_scores, test_scores = ms.validation_curve(model, x, y, param_name='max_depth', param_range=params, cv=5)
    scores = test_scores.mean(axis=1)
    # 验证曲线可视化
    plt.grid(linestyle=':')
    plt.plot(params, scores, 'o-', color='orangered', label='max_depth VC')
    plt.legend()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    请添加图片描述

    # 学习曲线,选取最优训练集大小
    params = np.arange(0.1, 1.1, 0.1)
    _, train_scores, test_scores = ms.learning_curve(model, x, y, train_sizes=params, cv=5)
    scores = test_scores.mean(axis = 1)
    
    # 学习曲线可视化
    plt.grid(linestyle=':')
    plt.plot(params, scores, 'o-', color='green', label='Learning Curve')
    plt.legend()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    请添加图片描述

    # 模型评估(先用训练样本进行模型评估)
    model.fit(x, y)
    pred_y = model.predict(x)
    print(sm.classification_report(y, pred_y))
    print(sm.confusion_matrix(y,pred_y)) # 把1类别的全归到0类别里了
    """
                  precision    recall  f1-score   support
    
               0       0.96      1.00      0.98       384
               1       1.00      0.75      0.86        69
               2       1.00      1.00      1.00      1210
               3       0.94      1.00      0.97        65
    
        accuracy                           0.99      1728
       macro avg       0.97      0.94      0.95      1728
    weighted avg       0.99      0.99      0.99      1728
    
    [[ 383    0    0    1]
     [  14   52    0    3]
     [   3    0 1207    0]
     [   0    0    0   65]]
    """
    
    data = [
        ['high', 'med', '5more', '4', 'big', 'low', 'unacc'],
        ['high', 'high', '4', '4', 'med', 'med', 'acc'],
        ['low', 'low', '2', '4', 'small', 'high', 'good'],
        ['low', 'med', '3', '4', 'med', 'high', 'vgood']
    ]
    test_data = pd.DataFrame(data)
    for col_ind, col_val in test_data.items():
        encoder = encoders[col_ind]
        encoded_col = encoder.transform(col_val)
        test_data[col_ind] = encoded_col
    # 整理输入集与输出集
    test_x, test_y = test_data.iloc[:,:-1], test_data[6]
    pred_test_y = model.predict(test_x)
    encoders[6].inverse_transform(pred_test_y)
    """
    array(['unacc', 'acc', 'good', 'vgood'], dtype=object)
    """
    
    • 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
  • 相关阅读:
    找到实现虚实结合的正确的方式和方法,并且让区块链的功能和作用得到最大地发挥
    【C++】线程库
    如何分析一篇论文或者是期刊?
    解析SOLIDWORKS教育版与企业版:选择合适版本,助力创新设计
    OpenHarmony鸿蒙南向开发案例:【智能门铃】
    shiro介绍和使用
    白话电子签章原理及风险
    【spring cloud】(三)服务降级——Hystrix
    0906几个内核前缀
    STM32第九节(中级篇):RCC(第一节)——时钟树讲解
  • 原文地址:https://blog.csdn.net/sgsgkxkx/article/details/125308527