机器学习之决策树(Decision Tree)

1. 决策树概念

决策树是根据特征进行树的构造,主要内容如下:
通过属性构造节点:
(1)二元属性

有房

(2)三元属性

婚姻
单身
已婚
离婚

(3)序数属性:离散化或者分区间进行分支
根据指标选择属性:
信息熵:
E n t r o p y = − ∑ i = 0 n − 1 p ( i ) l o g 2 p ( i ) Entropy=-\sum_{i=0}^{n-1}p(i)log_2p(i) Entropy=i=0n1p(i)log2p(i)
Gini值:
G i n i = 1 − − ∑ i = 0 n − 1 [ p ( i ) ] 2 Gini=1--\sum_{i=0}^{n-1}[p(i)]^2 Gini=1i=0n1[p(i)]2
如, l a b e l = 0 label=0 label=0的样本有5个, l a b e l = 1 label=1 label=1的样本也有5个,则有 p ( 0 ) = 0.5 p(0)=0.5 p(0)=0.5, p ( 1 ) = 0.5 p(1)=0.5 p(1)=0.5,对应的Gini值: G i n i = 1 − ∑ i = 0 1 [ p ( i ) ] 2 = 1 − [ 0. 5 2 + 0. 5 2 ] = 0.5 Gini=1-\sum_{i=0}^{1}[p(i)]^2=1-[0.5^2+0.5^2]=0.5 Gini=1i=01[p(i)]2=1[0.52+0.52]=0.5
根据属性计算对应的Gini值或者Entropy来选择作为节点的属性,对应值越小的属性越好。分支后的Gini值或Entropy是通过子节点的值加权和得到的,通过属性选择后使得指标变小,上一层节点的对应指标值和下一层的差就称为信息增益(熵值下降或Gini系数降低,意味着纯度上升)。
进一步选取子节点的方案:

  1. ID3
    信 息 增 益 = 原 始 熵 值 − 下 降 后 的 熵 值 信息增益=原始熵值-下降后的熵值 =选取使得信息增益最大的方案
  2. C4.5
    信 息 增 益 率 = 信 息 增 益 / 自 身 熵 值 信息增益率=信息增益/自身熵值 =/
  3. Gini系数的增益

决策树的评价函数: C ( T ) = ∑ t ∈ l e a f N t H ( t ) C(T)=\sum_{t\in leaf}N_tH(t) C(T)=tleafNtH(t)其中 N t N_t Nt为当前叶子节点样本个数, H ( t ) H(t) H(t)则表示当前叶子结点的熵值或Gini值。
决策树剪枝:决策树高度过高容易过拟合。
{ 预 剪 枝 : 在 构 建 决 策 树 的 过 程 提 前 截 止 后 剪 枝 : 决 策 树 构 建 好 后 再 进 行 裁 剪 \begin{cases} 预剪枝:在构建决策树的过程提前截止 \\ 后剪枝:决策树构建好后再进行裁剪 \end{cases} {
预剪枝方法:指定深度/指定最小样本数
后剪枝方法:
后剪枝损失函数: C α ( T ) = C ( T ) + α ∣ T l e a f ∣ C_\alpha (T)=C(T)+\alpha |T_{leaf}| Cα(T)=C(T)+αTleaf其中 α \alpha α表示叶子节点个数对结果的影响程度, T l e a f T_{leaf} Tleaf的加入会使得叶子节点数越多,损失就越大。遍历节点,按后剪枝损失函数确定是否进行修剪。

2. 决策树实操

2.1 决策树多分类

import matplotlib.pyplot as plt
import pydotplus
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split

# 导入红酒数据集
wine = load_wine()
# 划分成训练集和测试集
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data, wine.target, test_size=0.3)

# 实例化分类器
# random_state控制随机性
# 确定最优参数
test_scores = []
for i in range(10):
    clf = tree.DecisionTreeClassifier(criterion='entropy', random_state=30, splitter='random',
                                      max_depth=i+1)
    clf = clf.fit(Xtrain, Ytrain)
    score = clf.score(Xtest, Ytest)  # 返回预测的准确度
    test_scores.append(score)
plt.plot(range(1, 11), test_scores, color='red', label='max_depth')
plt.legend()
plt.show()
print(score)
score1 = clf.score(Xtrain, Ytrain)
print(score1)
import graphviz

feature_name = ['酒精', '苹果酸', '灰', '灰的碱性', '镁', '总酚', '类黄酮', '非黄烷类酚类', '花青素',
                '颜色强度', '色调', 'od280/od315稀释葡萄酒', '脯氨酸']

# filled属性是填充颜色
# rounded属性是框的形状
dot_data = tree.export_graphviz(clf, feature_names=feature_name,
                                class_names=['琴酒', '雪莉', '贝尔摩德'],
                                filled=True,
                                rounded=True)

# 决策树的可视化
graph = pydotplus.graph_from_dot_data(dot_data)
graph.write_png('1.png')
print([*zip(feature_name, clf.feature_importances_)])

2.2 决策树回归

from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeRegressor
import numpy as np
import matplotlib.pyplot as plt

# boston = load_boston()
# # 构建回归树
# regressor = DecisionTreeRegressor(random_state=0)
# # 10次交叉验证
# cross_val_score(regressor, boston.data, boston.target, cv=10,
#                 scoring='neg_mean_squared_error')
# print(cross_val_score)
rng = np.random.RandomState(1)
# (80,1)二维
X = np.sort(5 * rng.rand(80, 1), axis=0)
# ravel()降维函数修改成一维数据
y = np.sin(X).ravel()
# plt.figure()
# plt.scatter(X, y, s=20, edgecolors='black', c='darkorange', label='data')
# plt.show()
# 在y的数据上加入噪声,每隔5个步长加入噪声
y[::5] += 3 * (0.5 - rng.rand(16))
# plt.figure()
# plt.scatter(X, y, s=20, edgecolors='black', c='darkorange', label='data')
# plt.show()
regr_1 = DecisionTreeRegressor(max_depth=2)
regr_2 = DecisionTreeRegressor(max_depth=5)
regr_1.fit(X, y)
regr_2.fit(X, y)
# 生成0.0-5.0之间的步长为0.01的有序数列
# [:np.newaxis]用于扩展维度生成shape(n,1)
X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]
y_1 = regr_1.predict(X_test)
y_2 = regr_2.predict(X_test)
plt.figure()
plt.scatter(X, y, s=20, edgecolors='black', c='darkorange', label='data')
plt.plot(X_test, y_1, color='cornflowerblue', label='max_depth=2', linewidth=2)
plt.plot(X_test, y_2, color='yellowgreen', label='max_depth=5', linewidth=2)
plt.xlabel('data')
plt.ylabel('target')
plt.title('Decision Tree Regression')
plt.legend()
plt.show()

2.3 决策树调参案例(Tatanic)

import pandas as pd
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV, train_test_split, cross_val_score

data = pd.read_csv(r'./titanic/train.csv')
# print(data.head()) # 展示前多少行
# print(data.info()) # 展示整个表

# 数据预处理
# 筛选特征,删除缺失值过多的特征,以及和幸存与否无关的特征,对列进行操作(列)
data.drop(['Cabin', 'Name', 'Ticket'], inplace=True, axis=1)
# data = data.drop(['Cabin', 'Name', 'Ticket'], inplace=False, axis=1)

# 处理缺失值(均值或中值)
data['Age'] = data['Age'].fillna(data['Age'].mean())

# 对于缺失比较小的样本直接删掉(行)
data = data.dropna()

# 查看Embarked属性有多少取值,转换非数值的特征,映射到数值取值(分类之间相互独立)
# S\C\Q三种,并转换成列表对应index:0\1\2
labels = data['Embarked'].unique().tolist()
data['Embarked'] = data['Embarked'].apply(lambda x: labels.index(x))

# 性别转换成二分类,将bool值转换成0-1
# loc为标签索引,数字索引对应iloc
data.loc[:, 'Sex'] = (data['Sex'] == 'male').astype(int)

# 将标签和特征分离
# 除了survive列之外的列
x = data.iloc[:, data.columns != 'Survived']
y = data.iloc[:, data.columns == 'Survived']

Xtrian, Xtest, Ytrain, Ytest = train_test_split(x, y, test_size=0.3)
# 恢复索引,恢复成正序,避免索引发生混乱
for i in [Xtrian, Xtest, Ytrain, Ytest]:
    i.index = range(i.shape[0])

# clf = DecisionTreeClassifier(random_state=25)
# clf = clf.fit(Xtrian, Ytrain)
# # score = clf.score(Xtest, Ytest)
# score = cross_val_score(clf, x, y, cv=10).mean()
# print(score)
# tr = []
# te = []
# for i in range(10):
#     clf = DecisionTreeClassifier(random_state=25,
#                                  max_depth=i+1,
#                                  criterion='entropy')
#     clf = clf.fit(Xtrian, Ytrain)
#     score_tr = clf.score(Xtrian, Ytrain)
#     score_te = cross_val_score(clf, x, y, cv=10).mean()
#     tr.append(score_tr)
#     te.append(score_te)
#
# print(max(te))
# plt.plot(range(1, 11), tr, color='red', label='train')
# plt.plot(range(1, 11), te, color='blue', label='test')
# plt.xticks(range(1, 11))
# plt.legend()
# plt.show()

# 网格搜索调整多个参数,枚举技术,计算量很大
# 一串参数及其对应的取值范围的字典
import numpy as np
gini_thresholds = np.linspace(0, 0.5, 50)
# entrop[y_thresholds = np.linspace(0, 1, 50)
# 一般一两个参数组合,分别进行调试
# 过多的参数组合,会导致分数无法舍弃,得到的是平均的调参结果
parameters = {
    'criterion': ('gini', 'entropy')
    , 'splitter': ('best', 'random')
    , 'max_depth': [*range(1, 10)]
    , 'min_samples_leaf': [*range(1, 50, 5)]
    , 'min_impurity_decrease': [*np.linspace(0, 0.5, 20)]
}

clf = DecisionTreeClassifier(random_state=25)
GS = GridSearchCV(clf, parameters, cv=10)
GS.fit(Xtrian, Ytrain)
GS.best_params_  # 返回输入的参数列表的最佳组合
GS.best_score_  # 网格搜索后的模型评判标准
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值