机器学习-决策树

推导: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   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值