推导:day07 02:03:06-02:07:06
决策树(分类):
决策树的预测:
-1. 根据输入的样本x的特征属性和决策树中的决策树的取值,将输入的x样本落到某个叶子节点i中
-2. 将叶子节点i中的出现数量最多的那个类别作为输入的x样本的预测类别
备注:因为一个叶子节点中的所有样本应该是满足相同特性的样本数据,所以可以把每个叶子当做一
种"样本数据类别",这个类别的预测值应该就是这个节点中的大多数的那个类别信息。
决策树的构建:
目的:最优的模型应该是叶子节点中只包含一个类别的数据 ===> (节点中包含的样本数据)每次对节
点构建子节点的时候,只有一个目的:就是让节点中的数据尽可能的只包含一个类别的数据,也就是节
点数据尽可能的"纯"
重点:每次选择划分之后数据变的更"纯"的特征属性作为当前的划分特征属性
纯度的度量方式:Gini、信息熵、错误率;一般情况下,选择信息熵和Gini系数
Gain = 信息熵 - 条件熵
方式一缺点:可能这就是一个训练集上特殊的节点,但是实际情况这个节点根本不可能落到这个节点
上,这时候就会造成过拟合。
08_决策树构建流程讲解_转
决策树构建过滤理解.py
import numpy as np
"""
总样本:10条数据
是:3个样本
否:7个样本
特征1:房产
4个有房产
0个是 4个否
6个没有房产
3个是 3个否
特征2:婚姻情况
4个单身
2个是 2个否
3个已婚
0个是 3个否
3个离婚
1个是 2个否
特征3:年收入 60 75 85 90 95 100 100 110 125 220
"""
def h(ps):
"""
计算信息熵或者gini系数
:param ps: 各个的概率值
:return:
"""
# return 1.0 - np.sum([p * p for p in ps])
return np.sum([-p * np.log2(p) for p in ps])
def h(ps):
"""
计算信息熵
:param ps: 各个的概率值
:return:
"""
return 1.0 - np.sum([p * p for p in ps])
"""
总样本:10条数据
是:3个样本
否:7个样本
"""
print("寻找第一次的划分属性........")
info_d = h([0.3, 0.7])
print("在所有数据集中的目标属性的信息熵:{}".format(info_d))
"""
特征1:房产
4个有房产
0个是 4个否
6个没有房产
3个是 3个否
特征2:婚姻情况
4个单身
2个是 2个否
3个已婚
0个是 3个否
3个离婚
1个是 2个否
"""
# 遍历所有的特征,选择最优特征
# 1. 考虑特征一:房产 --> 计算条件熵
info_1_1 = h([1])
info_1_2 = h([0.5, 0.5])
info_1 = info_1_1 * 0.4 + info_1_2 * 0.6
print("在所有数据集中使用房产作为划分数据后的目标属性的信息熵:{}".format(info_1))
print("在所有数据集中使用房产作为划分的信息增益:{}".format(info_d - info_1))
# 2. 考虑特征二:婚姻情况 --> 计算条件熵
info_2_1 = h([0.5, 0.5])
info_2_2 = h([1])
info_2_3 = h([1 / 3, 2 / 3])
info_2 = info_2_1 * 0.4 + info_2_2 * 0.3 + info_2_3 * 0.3
print("在所有数据集中使用婚姻情况作为划分数据后的目标属性的信息熵:{}".format(info_2))
print("在所有数据集中使用婚姻情况作为划分的信息增益:{}".format(info_d - info_2))
分割的目录:让相同类别的数据尽可能放到同一个子树里面
# 3. 考虑特征二:年收入 --> 计算条件熵
info_3_1_1 = h([1])
info_3_1_2 = h([3 / 8, 5 / 8])
info_3_1 = info_3_1_1 * 0.2 + info_3_1_2 * 0.8
print("在所有数据集中使用年收入(80)作为划分数据后的目标属性的信息熵:{}".format(info_3_1))
print("在所有数据集中使用年收入(80)作为划分的信息增益:{}".format(info_d - info_3_1))
info_3_2_1 = h([2 / 5, 3 / 5])
info_3_2_2 = h([1])
info_3_2 = info_3_2_1 * 0.5 + info_3_2_2 * 0.5
print("在所有数据集中使用年收入(97.5)作为划分数据后的目标属性的信息熵:{}".format(info_3_2))
print("在所有数据集中使用年收入(97.5)作为划分的信息增益:{}".format(info_d - info_3_2))
使用信息增益最大的属性作为第一次划分属性:
如代码运行结果所知,年收入(97.5)可作为第一个划分属性
信息增益:年收入>房产> 婚姻情况
寻找第二属性的时候,年收入大于 97.5的样本就可以忽略了并且年收入不参与属性划分了, 所以
这里就剩下五个样本进行分析。
# 选择第二个分割点
print("以房产作为划分的条件熵:")
print(0.2 * h([1]) + 0.8 * h([0.75, 0.25]))
print("以婚姻情况作为划分的条件熵:")
print(0.4 * h([0.5, 0.5]) + 0.4 * h([1]) + 0.2 * h([1]))
然后一直往下划分......,最终得到我们想要的决策树模型
09_ID3、C45、CART三种决策树算法讲解_转
def h(ps):
"""
计算gini系数
:param ps: 各个的概率值
:return:
"""
return np.sum([-p * np.log2(p) for p in ps])
注意:代码都不用变,改变h(ps)即可
信息熵改成gini系数,最后得到的结果都一样,只是度量的指标不一样
10_案例代码:决策树实现鸢尾花数据分类案例代码讲解
**03:33:00- 讲解sklearn-tree的源码
决策树案例:鸢尾花数据分类.py
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.externals import joblib
from sklearn.metrics import f1_score, recall_score
import matplotlib as mpl
## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
# 1. 加载数据
# file_path = 'C:/workspace/python/sklearn07/datas/iris.data'
# file_path = 'file:///C:/workspace/python/sklearn07/datas/iris.data'
file_path = '../datas/iris.data'
names = ['sepal length', 'sepal width', 'petal length', 'petal width', 'cla']
df = pd.read_csv(file_path, header=None, names=names)
# print(df.head())
# print(df.info())
# 2. 提取数据
def parse_record(record):
result = []
r = zip(names, record)
for name, value in r:
if name == 'cla':
if value == 'Iris-setosa':
result.append(0)
elif value == 'Iris-versicolor':
result.append(1)
else:
result.append(2)
else:
result.append(value)
return result
datas = df.apply(lambda r: parse_record(r), axis=1)
# print(datas.head(10))
# print(datas.cla.value_counts())
x = datas[names[0:-1]]
y = datas[names[-1]]
# 3. 数据的分割
x_train, x_test, y_train, y_test = train_test_split
(x, y, train_size=0.9, random_state=28)
# 4. 决策树算法模型的构建
"""
# 给定采用gini还是entropy作为纯度的衡量指标
criterion="gini",
# 进行划分特征选择的时候采用什么方式来选择,best表示每次选择的划分特征都是全局最优的
(所有特征属性中的最优划分);random表示每次选择的划分特征不是所有特征属性中的最优特征,
而且先从所有特征中随机的抽取出部分特征属性,然后在这个部分特征属性中选择最优的,也就是
random选择的是局部最优。
# best每次都选择最优的划分特征,但是这个最优划分特征其实是在训练集数据上的这一个最优
划分。但是这个最优在实际的数据中有可能该属性就不是最优的啦(比如训练集中噪音点、特殊
样本),所以容易陷入过拟合的情况 --> 如果存在过拟合,可以考虑使用random的方式来选择。
splitter="best",
# 指定构建的决策树允许的最高层次是多少,默认不限制
max_depth=None,
# 指定进行数据划分的时候,当前节点中包含的数据至少要去的数据量
min_samples_split=2,
min_samples_leaf=1,
min_weight_fraction_leaf=0.,
# 在random的划分过程中,给定每次选择局部最优划分特征的时候,使用多少个特征属性
max_features=None,
random_state=None,
max_leaf_nodes=None,
min_impurity_split=1e-7,
class_weight=None,
presort=False
"""
algo = DecisionTreeClassifier(criterion="gini")
# 5. 算法模型的训练
algo.fit(x_train, y_train)
# 6. 模型效果评估
# 看方法的注释的方法:按ctrl键,同时鼠标在方法上左键点击
print("训练集上的准确率:{}".format(algo.score(x_train, y_train)))
print("测试集上的准确率:{}".format(algo.score(x_test, y_test)))
print("训练集上的F1值:{}".format(f1_score(y_train, algo.predict(x_train), average='macro')))
print("测试集上的F1值:{}".format(f1_score(y_test, algo.predict(x_test), average='macro')))
print("训练集上的召回率:{}".format(recall_score(y_train, algo.predict(x_train), average='macro')))
print("测试集上的召回率:{}".format(recall_score(y_test, algo.predict(x_test), average='macro')))
# 7. 模型保存
joblib.dump(algo, './model/algo.m')
01_决策树案例一:鸢尾花数据分类.ipynb
**03:50:00-04:16:00 讲解源码
11_决策树过拟合优化之剪枝操作讲解
剪枝需要了解一下,所有的决策树默认自带前置减枝,但是原理还是要了解一下
12_分类决策树和回归决策树的区别讲解
解决回归问题时候一般用均值来作为叶子节点的预测值
方差作为树的评价指标(方差越小,说明叶子节点上的所有值就越趋于均值)
一般只有CART算法构建回归树
**04:09:30
13_ID3、C45、CART三种决策树算法总结比较
14_决策树可视化方式及案例代码讲解
**04:54:00