欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DecisionTree --- 决策树

程序员文章站 2024-02-16 13:17:16
...

一、什么是决策树

        决策树是附加概率结果的一个树状的决策图,是直观的运用统计概率分析的图法。机器学习中决策树是一个预测模型,它表示对象属性和对象值之间的一种映射,每个内部结点表示在一个属性上的测试,每个分支代表一个属性输出,而每个树叶结点代表类或类分布,树的最顶层是根结点。

 

二、决策树案例

案例:

DecisionTree --- 决策树

 

决策树: 

DecisionTree --- 决策树

 

三、决策树建立

        决策树的建立首先要确定选择特征,选择一个合适的特征作为判断节点,可以快速的分类,减少决策树的深度。决策树的目标就是把数据集按对应的类标签进行分类。最理想的情况是,通过特征的选择能把不同类别的数据集贴上对应类标签。特征选择的目标使得分类后的数据集比较纯。如何衡量一个数据集纯度,这里就需要引入数据纯度函数。

 

3.1、信息增益

        信息熵表示的是不确定度。均匀分布时,不确定度最大,此时熵就最大。当选择某个特征对数据集进行分类时,分类后的数据集信息熵会比分类前的小,其差值表示为信息增益。信息增益可以衡量某个特征对分类结果的影响大小。

 

3.1.1、公式讲解:

(1)假设在样本数据集 D 中,混有 c 种类别的数据。构建决策树时,根据给定的样本数据集选择某个特征值作为树的节点。在数据集中,可以计算出该数据中的信息熵:

DecisionTree --- 决策树

其中 D 表示训练数据集,c 表示数据类别数,Pi 表示类别 i 样本数量占所有样本的比例。

 

(2)对应数据集 D,选择特征 A 作为决策树判断节点时,在特征 A 作用后的信息熵的为 Info(D),计算如下:

DecisionTree --- 决策树

其中 k 表示样本 D 被分为 k 个部分。

 

(3)信息增益表示数据集 D 在特征 A 的作用后,其信息熵减少的值。公式如下:

DecisionTree --- 决策树

对于决策树节点最合适的特征选择,就是 Gain(A) 值最大的特征。

 

3.1.2、结合案例讲解:

(1)根据上述提到的案例进行对应分析,首先我们需要确定的是根节点,那么根据上述案例可以获得,总共有14条记录数据,buys_computer的目标有yes or no,yes的数据有9条,no的数据有5条,则可以得出信息增益如下:

DecisionTree --- 决策树

 

(2)我们在分别求出不同属性的信息增益
以Age为例,由于Age分为了3类(youth占5条记录中yes有2条no有3条、middle_aged占4条记录中yes有4条no有0条、senior占5条记录中yes有3条no有2条),公式如下:

DecisionTree --- 决策树

其他分别是:

DecisionTree --- 决策树

DecisionTree --- 决策树

DecisionTree --- 决策树

 

(3)分别求出Gain(A),Gain(A) 值最大的作为特征节点

DecisionTree --- 决策树

DecisionTree --- 决策树

DecisionTree --- 决策树

DecisionTree --- 决策树

所以age作为根节点,树形图如下:

DecisionTree --- 决策树

 

(4)最后根据如上图的结果重复获取节点直至完成决策树

 

四、Python实现决策树

4.1、PyCharm中安装scikit-learn、numpy、sciPy和matplotlib

 

4.2、安装Graphviz,用于打开dot文件查看决策树

官网下载地址:https://graphviz.gitlab.io/_pages/Download/Download_windows.html

参考链接:https://www.cnblogs.com/shuodehaoa/p/8667045.html

 

4.3、代码如下:

from sklearn.feature_extraction import DictVectorizer #格式化数据成整形类数据
import csv
from sklearn import tree
from sklearn import preprocessing

# 打开csv文件
allElectronicsData = open(r'E:\workspace-pc\2018-09-04\01DTree\AllElectronics.csv', 'rt')
# 读取csv文件数据
reader = csv.reader(allElectronicsData)
# next表示读取csv文件中的头所在的行
headers = next(reader)
print("读取的csv文件中的头行信息:%s"%headers)

# 特征值
featureList = []
# 目标值
labelList = []

for row in reader:
    labelList.append(row[len(row)-1])
    rowDict = {}
    for i in range(1, len(row)-1):
        rowDict[headers[i]] = row[i]
    featureList.append(rowDict)

print(featureList)

# 将featureList中的特征值转化成sklearn可识别的整型值,转化以0,1表示
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList).toarray()

print("dummyX: " + str(dummyX))
# vec.get_feature_names():获取所有的特征值,如下:
# ['age=middle_aged', 'age=senior', 'age=youth', 'credit_rating=excellent', 'credit_rating=fair',...]
print(vec.get_feature_names())
print("labelList: " + str(labelList))

# 将labelList中的目标值转化成sklearn可识别的整型值,转化以0,1表示
lb = preprocessing.LabelBinarizer()
dummyY = lb.fit_transform(labelList)
print("dummyY: " + str(dummyY))


# 创建决策树
clf = tree.DecisionTreeClassifier(criterion='entropy')
clf = clf.fit(dummyX, dummyY)
print("clf: " + str(clf))


# 输出graphviz的dot文件,输出的dot文件可以通过graphviz工具查看Tree型图
with open("allElectronicInformationGainOri.dot", 'w') as f:
    tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)



# 预测新数据结果
oneRowX = dummyX[0, :]
print("oneRowX: " + str(oneRowX))
newRowX = oneRowX
newRowX[0] = 1
newRowX[2] = 0
print("newRowX: " + str(newRowX))

# reshape(1,-1)表示将newRowX转换一个新的形态(1表示一行,-1表示未知列数)
predictedY = clf.predict(newRowX.reshape(1, -1))
print("predictedY: " + str(predictedY))


说明:

clf = tree.DecisionTreeClassifier(criterion='entropy')

在创建决策树时可以选择的参数如下:(官网参数说明

class sklearn.tree.DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None, min_samples_split=2,min_samples_leaf =1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None,class_weight=None, presort=False)

criterion:string类型,可选(默认为"gini"):

衡量分类的质量。支持的标准有"gini"代表的是Gini impurity(不纯度)与"entropy"代表的是information gain(信息增益)。


splitter:string类型,可选(默认为"best")

一种用来在节点中选择分类的策略。支持的策略有"best",选择最好的分类,"random"选择最好的随机分类。


max_features:int,float,string or None 可选(默认为None)

在进行分类时需要考虑的特征数。

  1. 如果是int,在每次分类是都要考虑max_features个特征。
  2. 如果是float,那么max_features是一个百分率并且分类时需要考虑的特征数是int(max_features*n_features,其中n_features是训练完成时发特征数)。
  3. 如果是auto,max_features=sqrt(n_features)
  4. 如果是sqrt,max_features=sqrt(n_features)
  5. 如果是log2,max_features=log2(n_features)
  6. 如果是None,max_features=n_features

注意:至少找到一个样本点有效的被分类时,搜索分类才会停止。


max_depth:int or None,可选(默认为"None")

表示树的最大深度。如果是"None",则节点会一直扩展直到所有的叶子都是纯的或者所有的叶子节点都包含少于

min_samples_split个样本点。忽视max_leaf_nodes是不是为None。

 

min_samples_split:int,float,可选(默认为2)

区分一个内部节点需要的最少的样本数。

  1. 如果是int,将其最为最小的样本数。
  2. 如果是float,min_samples_split是一个百分率并且ceil(min_samples_split*n_samples)是每个分类需要的样本数。ceil是取大于或等于指定表达式的最小整数。


min_samples_leaf:int,float,可选(默认为1)

一个叶节点所需要的最小样本数:

  1. 如果是int,则其为最小样本数
  2. 如果是float,则它是一个百分率并且ceil(min_samples_leaf*n_samples)是每个节点所需的样本数。


min_weight_fraction_leaf:float,可选(默认为0)

一个叶节点的输入样本所需要的最小的加权分数。


max_leaf_nodes:int,None 可选(默认为None)

在最优方法中使用max_leaf_nodes构建一个树。最好的节点是在杂质相对减少。如果是None则对叶节点的数目没有限制。如果

不是None则不考虑max_depth.


class_weight:dict,list of dicts,"Banlanced" or None,可选(默认为None)

表示在表{class_label:weight}中的类的关联权值。如果没有指定,所有类的权值都为1。对于多输出问题,一列字典的顺序可以与

一列y的次序相同。"balanced"模型使用y的值去自动适应权值,并且是以输入数据中类的频率的反比例。如:

n_samples/(n_classes*np.bincount(y))。

对于多输出,每列y的权值都会想乘。

如果sample_weight已经指定了,这些权值将于samples以合适的方法相乘。


random_state:int,RandomState instance or None

如果是int,random_state 是随机数字发生器的种子;如果是RandomState,random_state是随机数字发生器,如果是None,随机

数字发生器是np.random使用的RandomState instance.


persort:bool,可选(默认为False)

是否预分类数据以加速训练时最好分类的查找。在有大数据集的决策树中,如果设为true可能会减慢训练的过程。当使用一个小

数据集或者一个深度受限的决策树中,可以减速训练的过程。