深度学习基础01----决策树算法与应用详解

决策树属于监督学习的一种,是非常常用的分类方法,是机器学习中一个非常重要的算法,那么,什么是决策树?从字面上看“决策树”分为两大部分,“决策”和“树”,“决策”就是判断嘛,那“树“就是说它的形状像树,有结点有分支
在这里插入图片描述
如上图所示,决策树是一个类似于流程图的树结构,每个结点代表一个属性上的测试,每个分支代表一个属性的输出,每个树叶结点代表类或类分布,树的最顶层是根结点。
构造决策树之前我们先来了解一个基本概念:熵
1948年,香农提出了“熵”的概念:
一条信息的信息量大小和它的不确定性有直接的关系,要搞清楚一件非常非常不确定的事情,或者是我们一无所知的事情,需要了解大量信息==>信息量的度量就等于不确定性的多少。这个概念理解起来确实非常抽象,我们先暂且了解一下,计算公式如下:
H(x) = E[I(xi)] = E[ log(2,1/P(xi)) ] = -∑P(xi)log(2,P(xi)) (i=1,2,…n)
其中,x表示随机变量,与之相对应的是所有可能输出的集合,定义为符号集,随机变量的输出用x表示。P(x)表示输出概率函数。变量的不确定性越大,熵也就越大,把它搞清楚所需要的信息量也就越大。

接下来写一下决策树归纳算法,即非常经典的ID3算法:
选择属性判断结点
信息获取量(Information Gain):Gain(A)=Info(D)-Infor_A(D)通过A作为节点分类获取了多少信息
以下面一组数据为例来具体计算一下:
在这里插入图片描述
这组数据是不同年龄段,不同收入,是否是学生,购买电脑的数据
在这里插入图片描述
所以年龄的信息获取量为:
在这里插入图片描述
同理,我们可以计算出以收入,是否是学生,信用评级情况为节点计算信息获取量,分别为:
在这里插入图片描述
以年龄为节点信息获取量最大,所以我们选择以年龄作为根节点,构造决策树如下:
在这里插入图片描述
所以ID3的算法可以总结如下:
在这里插入图片描述
还有一些贪心算法和自上而下算法来构造决策树,有兴趣可以自己了解一下

决策树的优点是直观,便于理解,对小规模数据集很有效,但是它处理连续变量不好,当类别较多的时候,错误增加的很快,可规模性也很一般
来编程实现一个简单的例子:
我们需要首先安装graphviz,它有助于将决策树可视化,安装和配置方法在我的这篇博客:Graphvia安装及配置
来认识一下我们主要使用的库:scikit-learn
它有以下几个特性:(1)进行简单高效的数据挖掘和机器学习分析
(2)对所有用户开放,根据不同需求高度可重用性
(3)开源,达到商用级别,获得BSD认可
它覆盖非常多的问题领域,比如:分类,回归,聚类,降维,模型选择,预处理在这里插入图片描述它的安装和配置可以参考我的这篇博客:scikit-learn库安装及配置

首先引入必要的包和模块:

from sklearn.feature_extraction import DictVectorizer #sklearn对数据输入有一定要求,通过DictVectorizer进行数据转化
import csv  #原始数据存于csv文件
from sklearn import preprocessing # 数据预处理
from sklearn import tree #决策树
from six import StringIO  #进行I/O读写

读取csv文件:

allElectronicsData = open('play.csv','rt')
reader = csv.reader(allElectronicsData)
header=next(reader)

play.csv文件内容,就是我上面提到的例子
在这里插入图片描述
将每一行数据的属性和类别分别存储

featureList=[] #储存属性
labelList=[] #储存分类
for row in reader:
    labelList.append(row[len(row)-1])#每一行的最后一个属性
    rowDict={}#创建字典,每一行的所有特征
    for i in range(1,len(row)-1):
        rowDict[header[i]]=row[i]
        
        featureList.append(rowDict)

featureList内容:
在这里插入图片描述
在这里插入图片描述
labelList内容:
在这里插入图片描述
sklearn要求数据输入为数字型,但是我们的数据为文字型,所以我们首先要进行一个转换,使用preprocessing包来自动完成

vec = DictVectorizer()#实例化
dumpyX = vec.fit_transform(featureList).toarray()#转化为离散格式0,1


lb = preprocessing.LabelBinarizer()#直接调用模块
dummyY = lb.fit_transform(labelList)#将标签二值化

在这里插入图片描述
出现了9行,是因为改组数据变量一共9个可取值,age变量有3个可取值,所以前三列均代表的age,001代表youth,100代表middle,010代表senior

在这里插入图片描述
接下来创建分类器,构造决策树

clf = tree.DecisionTreeClassifier(criterion='entropy')
clf = clf.fit(dumpyX,dummyY) #构造决策树

criterion的属性值即为选择哪种方法,DecisionTreeClassifier包括以下属性

# =============================================================================
# criterion : 默认为 "gini"。是特征选择的标准,可选择基尼系数 "gini" 或者 信息熵 "entropy"。
# splitter : 默认为 "best"。"best" 是在特征的所有划分点中找出最优的划分点。"random" 是随机的在部分划分点中找局部最优的划分点。"best" 适合样本量不大的时候,如果样本数据量非常大,推荐 "random"。
# max_depth : 默认为 None。设置树的最大深度。如果是 None,则不限制子树的深度,直到所有叶子是纯的,或者所有叶子包含少于 min_samples_split 的样本。
# min_samples_split : 默认为 2,可以是 int 或者 float 格式。限制子树继续划分的条件,如果节点的样本数小于这个值,则不会再划分。当为 float 值时,拆分的最小样本数为 ceil(min_samples_split * n_samples)。
# min_samples_leaf : 默认为1,可以是 int 或者 float 格式。设置叶子节点的最小样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。当为 float 值时,此时叶子最小样本数为 ceil(min_samples_leaf * n_samples)。
# min_weight_fraction_leaf : 叶子节点最小的样本权重和。这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。 默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。
# max_features : 划分时考虑的最大特征数,默认为 None。是划分时考虑的最大特征数,
# 如果是 int, 最大特征数为此 max_features 值。
# 如果是 float,  值为 int(max_features * n_features)。
# 如果是 “auto”, 值为 max_features=sqrt(n_features)。
# 如果是 “sqrt”, 值为 max_features=sqrt(n_features)。
# 如果是 “log2”, 值为 max_features=log2(n_features)。
# 如果是 None, 值为 max_features=n_features 表示划分时考虑所有的特征数。
# random_state : 默认为 None。随机种子。
# max_leaf_nodes : 最大叶子节点数,默认为 None。限制最大叶子节点数,可以防止过拟合如果为 None,则不显示最大的叶子节点数。
# class_weight : 指定样本各类别的的权重。默认为 None,表示没有权重偏倚。如果为 "balanced",则算法会自己计算权重,样本少的权重高,公式:n_samples / (n_classes * np.bincount(y))。
# min_impurity_decrease : 默认为0。参数的意义是,如果继续分裂能减少的杂质大于或等于该值,则分裂节点。
# min_impurity_split : 如果节点的不纯度高于阈值,节点将分裂。(已被 min_impurity_decrease 代替)。
# presort : 设置数据是否预排序,默认为 False。在大型数据集上,设置为 True 可能反而会降低训练速度,在较小数据集或者限制深度的树上使用 True 能加快训练速度。
# 属性:
# max_features_ : 特征的数量
# feature_importances_ : 特征的重要性。
# =============================================================================

打印构建好的决策树

#创建新的文件play.dot

with open('play.dot','w') as f:
  f=tree.export_graphviz(clf,feature_names=vec.get_feature_names(),out_file=f)
#把0和1还原原来变量的名字,feature_names=vec.get_feature_names()

查看写出的dot文件:在这里插入图片描述

转化为pdf文件画出来
打开cmd,找到dot文件所在路径,输入:

dot -Tpdf play.dot -o out.pdf
#play.doy为原始dot文件,out.pdf为你想要输出的文件及类型
#Tpdf为转为pdf

在这里插入图片描述
画出的决策树简直太漂亮了

最后我们来检测一下模型

#验证数据,取一行数据,修改几个属性预测结果
oneRowX=dumpyX[0,:].reshape(1, -1)#取第一行数据
print("oneRowX: "+str(oneRowX))
newRowX = oneRowX
newRowX[0][0] = 0#更改个别变量
newRowX[0][2] = 1#更改个别变量
newRowX.reshape(1, -1)

predictedY = clf.predict(newRowX)#预测数据

在这里插入图片描述

ok,就这样啦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值