【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)
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]
"""
8. 集合模型分类实现
  • 集合模型提供的常用分类器
import sklearn.ensemble as se

model = se.RandomForestClassifier(...) # 随机森林分类器
model = se.AdaBoostClassifier(...) # AdaBoost分类器
model = se.GridientBoostingClassifier(...) # GBDT分类器

二、预测小汽车等级

  • car.txt 样本文件中统计了小汽车的常见特征信息及小汽车的分类,使用这些数据基于决策树分类算法训练模型预测小汽车等级。
  • 汽车价格 维修费用 车门数量 载客数 后备箱 安全性 汽车级别
  • 分析实现思路:
    • 加载数据。
    • 特征分析与特征工程。
    • 数据预处理(标签编码)。
    • 训练模型。
    • 模型测试。
import numpy as np
import pandas as pd

data = pd.read_csv('car.txt', header=None) # 不想把第一行当做表头
data.head()

请添加图片描述

data[0].value_counts() # 汽车价格分成4类,按类别划分每个类别有432个样本
"""
vhigh    432
low      432
med      432
high     432
Name: 0, dtype: int64
"""
  • 确定:是分类问题,还是回归问题?答:分类
  • 选哪一个分类模型:逻辑回归、决策树、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

请添加图片描述

# 整理输入集与输出集
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. 验证曲线
  • 验证曲线描述的关系即是模型性能关于模型超参数的函数关系:
    • 模型性能 = f(超参数)
2. 验证曲线实现
  • sklearn 提供的验证曲线 API:
train_scores, test_scores = ms.validation_curve(
	model,  # 模型
    输入集, 输出集,
    'n_estimators',  # 超参数名
    np.arange(50, 550, 50),	# 超参数序列
    cv=5	# 折叠数
)
  • 返回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()

请添加图片描述

# 调整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()

请添加图片描述

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)
"""
4. 学习曲线
  • 学习曲线描述的关系即是模型性能关于训练样本量大小的函数关系:
    • 模型性能 = f(训练集大小)
5. 学习曲线实现
  • sklearn 提供的学习曲线 API:
train_scores, test_scores = ms.learning_curve(
	model,  # 模型
    输入集, 输出集,
    train_sizes=[0.9, 0.8, 0.7],	# 训练集大小序列
    cv=5	# 折叠数
)
  • 返回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()

请添加图片描述

四、完整案例

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()

请添加图片描述

# 调整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()

请添加图片描述

# 学习曲线,选取最优训练集大小
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()

请添加图片描述

# 模型评估(先用训练样本进行模型评估)
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)
"""
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬小帽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值