决策树

决策树

决策树基于二分类思想,类似于编程语言中的if-else,决策树通常会有两个阶段:构造和剪枝。
  • 构造:构造的过程就是选择什么属性作为节点的过程。构造过程中会存在三种节点:

    1. 根节点:最开始的节点
    2. 内部节点:树中间的节点
    3. 叶节点:决策结果
  • 剪枝:目的是为了防止过拟合。可分为预剪枝和后剪枝。

    • 预剪枝是指在决策树构造时进行剪枝。在构造过程中对节点进行评估,如果对某个节点进行划分,在验证集中不能带来准确性的提升,那么对这个节点进行划分就没有意义,这时就会把当前节点作为叶节点,不对其进行划分。
    • 后剪枝是在生产决策树之后在进行剪枝。通常会从决策树的叶节点开始,逐层向上对每个节点进行评估。如果剪掉这个节点子树,与保留该节点子树在分类准确性上差别不大,或者剪掉该节点子树,能在验证集中带来准确性的提升,那么就可以把该节点子树进行剪枝。方法是:用这个节点子树的叶子节点来替代该节点,类标记为这个节点子树中最频繁的那个类。
选取根节点属性的指标:纯度和信息熵
ID3算法节点属性选择采用的指标是信息增益。(对噪声敏感)
  • ID3算法的缺点:倾向于选择取值比较多的属性,有些属性可能对分类任务没有太大作用,但仍然可能被选为最优属性。
C4.5算法节点属性选择采用的指标是信息增益率。(解决了ID3对噪声敏感的问题,但算法效率低)
  • 信息增益率=信息增益/属性熵,基于ID3缺点的改进。
  • 采用悲观剪枝,提升决策树泛化能力。悲观剪枝通过递归估算每个内部节点的分类错误率,比较剪枝前后这个节点的分类错误率来决定是否对其进行剪枝。
  • 离散化处理连续属性
  • 能够处理缺失值
Cart算法节点属性选择采用的指标是基尼指数。基尼系数越小,说明样本之间的差异性小,不确定程度低。
  • CART树既可作分类树,又可作回归树。
  • 基于基尼系数对特征属性进行二元分裂
例CART分类树:
# encoding=utf-8
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris

# 准备数据集
iris=load_iris()
# 获取特征集和分类标识
x = iris.data
y = iris.target
# 随机抽取33%的数据作为测试集,其余为训练集
train_x, test_x, train_y, test_y = train_test_split(x, y, test_size=0.33, random_state=0)
# 创建CART分类树
clf = DecisionTreeClassifier(criterion='gini')
# 拟合构造CART分类树
clf = clf.fit(train_x, train_y)
# 用CART分类树做预测
test_predict = clf.predict(test_x)
# 预测结果与测试集结果作比对
score = accuracy_score(test_y, test_predict)
print("CART分类树准确率 %.3lf" % score)
CART回归树通常采用差值的绝对值或方差来作为属性选取指标,对于这两种节点划分标准分别对应着两种目标函数最优化的标准,即最小绝对偏差(LAD)或最小二乘偏差(LSD).
例CART回归树:
# encoding=utf-8
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_boston
from sklearn.metrics import r2_score,mean_absolute_error,mean_squared_error
from sklearn.tree import DecisionTreeRegressor

# 准备数据集
boston=load_boston()
# 探索数据
print(boston.feature_names)
# 获取特征集和房价
x = boston.data
y = boston.target
# 随机抽取33%的数据作为测试集,其余为训练集
train_x, test_x, train_y, test_y = train_test_split(x, y, test_size=0.33)
# 创建CART回归树
dtr=DecisionTreeRegressor()
# 拟合构造CART回归树
dtr.fit(train_x, train_y)
# 预测测试集中的房价
predict_price = dtr.predict(test_x)
# 测试集的结果评价
print('回归树二乘偏差均值:', mean_squared_error(test_y, predict_price))
print('回归树绝对值偏差均值:', mean_absolute_error(test_y, predict_price)) 
CART决策树的剪枝:
  • 主要采用CCP方法,即代价复杂度。使用节点的表面误差率增益值作为剪枝前后误差的定义。
    α=C(t)−C(Tt)∣Tt∣−1 \alpha=\frac{C(t)-C\left(T_{t}\right)}{\left|T_{t}\right|-1} α=Tt1C(t)C(Tt)
    其中Tt代表以t为根节点的子树,C(Tt)表示节点t的子树没被裁剪时子树Tt的误差,C(t)表示节点t的子树被剪枝后节点t的误差,|Tt|代子树Tt的叶子数,剪枝后,T的叶子数减少了|Tt|-1。

  • 节点的表面误差率增益值等于节点t的子树被剪枝后的误差变化除以剪掉的叶子数量

sklearn中的决策树分类器:
DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=None,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=None,
            splitter='best')
参数作用
criterion选择特征的标准,默认gini,可指定entropy
splitter构造树时选择属性特征的原则,默认best代表在所有特征中选择最好的,可指定random代表在部分特征中选择最好
max_depth决策树最大深度
max_features划分数据集是考虑最大的特征值数量
min_samples_split当节点样本数少于这个值时,不再分裂。默认2
min_samples_leaf叶子节点需要的最少样本数
max_leaf_nodes最大叶子节点数
min_impurity_decrease节点划分最小不纯度
min_impurity_split信息增益的阈值
class_weight类别权重
presortbool类型,默认false,表示拟合前,是否对数据进行排序来加快树的构建,当数据集较小时,使用presort=true可以加快分类器构造速度,当数据集较大时,会导致整个分类非常缓慢
函数作用
fit(features,labels)通过特征矩阵、分类标识,让分类器进行拟合
predict(features)返回预测结果
score(features, labels)返回准确率
案例:泰坦尼克号生存预测
  1. 准备:首先对训练集、测试集数据探索,分析数据质量进行数据清洗,然后通过特征选择进行数据降维。
  2. 分类:通过训练集的特征矩阵、分类结果得到决策树分类器,然后将分类器应用于测试集,最后对分类器准确性进行分析。

第一步:数据探索

  • 使用info()了解数据表的基本情况:行数、列数、每列的数据类型、数据完整度;

  • 使用describe()了解数据表的统计情况:总数、平均值、标准差、最小值、最大值等;

  • 使用describe(include=[‘O’])查看字符串类型(非数字)的整体情况;

  • 使用head查看前几行数据(默认是前5行);

  • 使用tail查看后几行数据(默认是最后5行)

    import pandas as pd
    
    train_data = pd.read_csv('./train.csv')
    test_data = pd.read_csv('./test.csv')
    
    print(train_data.info())
    print('-'*30)
    print(train_data.describe())
    print('-'*30)
    print(train_data.describe(include=['O']))
    print('-'*30)
    print(train_data.head())
    print('-'*30)
    print(train_data.tail())
    

第二步:数据清洗

  • age,fare,cabin有缺失值,age和fare为数字型用平均值补齐。

    # 使用平均年龄来填充年龄中的nan值
    train_data['Age'].fillna(train_data['Age'].mean(), inplace=True)
    test_data['Age'].fillna(test_data['Age'].mean(),inplace=True)
    # 使用票价的均值填充票价中的nan值
    train_data['Fare'].fillna(train_data['Fare'].mean(), inplace=True)
    test_data['Fare'].fillna(test_data['Fare'].mean(),inplace=True)
    
  • cabin为船舱,有大量缺失值,无法补齐。embarked为登录港口,有少量缺失值,利用出现次数最多的港口补齐。

    # 使用登录最多的港口来填充登录港口的nan值
    train_data['Embarked'].fillna('S', inplace=True)
    test_data['Embarked'].fillna('S',inplace=True)
    

第三步:特征选择

  • PassengerId为乘客编号,Name为乘客姓名,对分类没有作用;Cabin字段缺失值太多,放弃;Ticket字段为船票号码,杂乱无章且无规律,放弃。

  • 其余字段包括:Pclass、Sex、Age、SibSp、Parch和Fare,分别对应乘客的船票等级、性别、年龄、亲戚数量以及船票价格。

  • 将Sex字段变成Sex=male和Sex=female两个字段,数值用0或1来表示。Embarked字段改成Embarked=S、Embarked=C和Embarked=Q三个字段,数值用0或1来表示。

    from sklearn.feature_extraction import DictVectorizer
    dvec=DictVectorizer(sparse=False)
    train_features=dvec.fit_transform(train_features.to_dict(orient='record'))
    
  • 特征选择后train_features为891行,10列的特征矩阵

第四步:决策树模型

from sklearn.tree import DecisionTreeClassifier
# 构造CART决策树
clf = DecisionTreeClassifier(criterion='entropy')
# 决策树训练
clf.fit(train_features, train_labels)

第五步:模型预测评估

test_features=dvec.transform(test_features.to_dict(orient='record'))
# 决策树预测
pred_labels = clf.predict(test_features)

import numpy as np
from sklearn.model_selection import cross_val_score
# 使用K折交叉验证 统计决策树准确率,这里是10折
print(u'cross_val_score准确率为 %.4lf' % np.mean(cross_val_score(clf, train_features, train_labels, cv=10)))

K折交叉验证原理:

  1. 将数据集平均分割成K个等份;
  2. 使用1份数据作为测试数据,其余作为训练数据;
  3. 计算测试准确率;
  4. 使用不同的测试集,重复2、3步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sweeney Chen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值