机器学习之决策树(Decision Tree)及其Python代码实现

简介:   决策树是一个预测模型;他代表的是对象属性与对象值之间的一种映射关系。树中每个节点表示某个对象,而每个分叉路径则代表的某个可能的属性值,而每个叶结点则对应从根节点到该叶节点所经历的路径所表示的对象的值。

  决策树是一个预测模型;他代表的是对象属性与对象值之间的一种映射关系。树中每个节点表示某个对象,而每个分叉路径则代表的某个可能的属性值,而每个叶结点则对应从根节点到该叶节点所经历的路径所表示的对象的值。决策树仅有单一输出,若欲有复数输出,可以建立独立的决策树以处理不同输出。数据挖掘中决策树是一种经常要用到的技术,可以用于分析数据,同样也可以用来作预测。

  从数据产生决策树的机器学习技术叫做决策树学习, 通俗说就是决策树。


  例如,我们要对”是否要出去玩?“这样的问题进行决策的时候,通常会进行一系列的判断或者”子决策“:我们先看”OUTLOOK“,如果是天气是sunny,则我们再看空气湿度,如果是”humidity<70“(湿度小于70),那么就去玩,否则就不去玩;如果天气是overcast,那么就去玩,其他的节点可以不用判断;以此类推:

这里写图片描述

  一般地,一颗决策树包含一个根节点,若干个 内部节点;叶节点对应与决策结果,其他每个节点对应于一个属性测试;每个节点包含的样本集合根据属性测试的结果被划分到子节点中;根节点包含样本全集。从根节点到每个叶节点的路径对应了一个判定测试序列。决策树学习的目的是为了产生一棵泛化能力强,即处理未见示例能力强的决策树,其基本流程遵循简单且直观的”分而治之“的策略,如下所示:

这里写图片描述


  在建立决策树之前,我们必须先要学习一个非常重要的概念,那就是信息熵

  1948年,香农提出了 ”信息熵(entropy)“的概念。 一条信息的信息量大小和它的不确定性有直接的关系,要搞清楚一件非常非常不确定的事情,或者是我们一无所知的事情,需要了解大量信息==>信息量的度量就等于不确定性的多少。

  信息熵是度量样本集合纯度最常用的一种指标。假定当前样本集合D中第K类样本所占的比例为[Math Processing Error],则D的信息熵的定义为:

这里写图片描述

  变量的不确定性越大,信息熵也就越大。


决策树归纳算法 (ID3)

  信息获取量(Information Gain):Gain(A) = Info(D) - Infor_A(D),其中 Info(D)代表没有加入A节点的所获取的信息量,Infor_A(D)代表加入A节点后所获取的信息量。
  一般而言,信息获取量越大,则意味着使用属性A来进行划分所获得的”纯度提升“越大。因此,我们可以用信息获取量来进行决策树的划分属性的选择,著名的ID3决策树学习算法就是以信息获取量为准则来选择划分属性的。

这里写图片描述

以上图中为例,

这里写图片描述
这里写图片描述

由上可得Gain(age) = Info(D) - Infor_A(D)=0.940-0.694=0.246。

类似,Gain(income) = 0.029, Gain(student) = 0.151, Gain(credit_rating)=0.048;

因为Gain(age)> Gain(student)>Gain(credit_rating)>Gain(income),所以,选择age作为第一个根节点。

这里写图片描述

重复以上步骤即可得出结论。


示例Python代码如下:

from sklearn.feature_extraction import DictVectorizer
import csv
from sklearn import tree
from sklearn import 

preprocessing
from sklearn.externals.six import StringIO

# Read in the csv file and put features into list of dict and 

list of class label
allElectronicsData = open

(r'/home/zhoumiao/MachineLearning/01decisiontree/AllElectronics.csv', 'rb')
reader = csv.reader

(allElectronicsData)
headers = reader.next()

print(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)

# Vetorize features
vec = DictVectorizer()
dummyX = 

vec.fit_transform(featureList) .toarray()

print("dummyX: " + str(dummyX))
print(vec.get_feature_names())

print

("labelList: " + str(labelList))

# vectorize class labels
lb = preprocessing.LabelBinarizer()
dummyY = 

lb.fit_transform(labelList)
print("dummyY: " + str(dummyY))

# Using decision tree for classification
# clf = 

tree.DecisionTreeClassifier()
clf = tree.DecisionTreeClassifier(criterion='entropy')
clf = clf.fit(dummyX, 

dummyY)
print("clf: " + str(clf))


# Visualize model
with open("allElectronicInformationGainOri.dot", 'w') as f:
    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))

predictedY = clf.predict(newRowX)
print("predictedY: " + str(predictedY))

其他算法:

1、C4.5: Quinlan
2、Classification and Regression Trees (CART): (L. Breiman, J. Friedman, R. Olshen, C. Stone)

共同点:都是贪心算法,自上而下(Top-down approach)

区别:属性选择度量方法不同: C4.5 (gain ratio), CART(gini index), ID3 (Information Gain)

  划分数据集的最大原则是:使无序的数据变的有序。如果一个训练数据中有20个特征,那么选取哪个做划分依据?这就必须采用量化的方法来判断,量化划分方法有多重,其中一项就是“信息论度量信息分类”。基于信息论的决策树算法有ID3、CART和C4.5等算法,其中C4.5和CART两种算法从ID3算法中衍生而来。

  CART和C4.5支持数据特征为连续分布时的处理,主要通过使用二元切分来处理连续型变量,即求一个特定的值-分裂值:特征值大于分裂值就走左子树,或者就走右子树。这个分裂值的选取的原则是使得划分后的子树中的“混乱程度”降低,具体到C4.5和CART算法则有不同的定义方式。

  ID3算法由Ross Quinlan发明,建立在“奥卡姆剃刀”的基础上:越是小型的决策树越优于大的决策树(be simple简单理论)。ID3算法中根据信息论的信息增益评估和选择特征,每次选择信息增益最大的特征做判断模块。ID3算法可用于划分标称型数据集,没有剪枝的过程,为了去除过度数据匹配的问题,可通过裁剪合并相邻的无法产生大量信息增益的叶子节点(例如设置信息增益阀值)。使用信息增益的话其实是有一个缺点,那就是它偏向于具有大量值的属性–就是说在训练集中,某个属性所取的不同值的个数越多,那么越有可能拿它来作为分裂属性,而这样做有时候是没有意义的,另外ID3不能处理连续分布的数据特征,于是就有了C4.5算法。CART算法也支持连续分布的数据特征。

  C4.5是ID3的一个改进算法,继承了ID3算法的优点。C4.5算法用信息增益率来选择属性,克服了用信息增益选择属性时偏向选择取值多的属性的不足在树构造过程中进行剪枝;能够完成对连续属性的离散化处理;能够对不完整数据进行处理。C4.5算法产生的分类规则易于理解、准确率较高;但效率低,因树构造过程中,需要对数据集进行多次的顺序扫描和排序。也是因为必须多次数据集扫描,C4.5只适合于能够驻留于内存的数据集。

这里写图片描述
这里写图片描述

  CART算法的全称是Classification And Regression Tree,采用的是Gini指数(选Gini指数最小的特征s)作为分裂标准,同时它也是包含后剪枝操作。ID3算法和C4.5算法虽然在对训练样本集的学习中可以尽可能多地挖掘信息,但其生成的决策树分支较大,规模较大。为了简化决策树的规模,提高生成决策树的效率,就出现了根据GINI系数来选择测试属性的决策树算法CART。


关于剪枝(避免过拟合(overfitting))

  在实际构造决策树时,通常要进行剪枝,这时为了处理由于数据中的噪声和离群点导致的过分拟合问题。剪枝有两种:

先剪枝:在构造过程中,当某个节点满足剪枝条件,则直接停止此分支的构造。

后剪枝:先构造完成完整的决策树,再通过某些条件遍历树进行剪枝。


决策树的优缺点

优点:直观,便于理解,小规模数据集有效

缺点:1.处理连续变量不好;
   2.类别较多时,错误增加的比较快;
   3.可规模性一般。


参考: 机器学习经典算法详解及Python实现–决策树(Decision Tree)

参考: <<统计学习方法— 李航>>


机器学习系列之机器学习之Validation(验证,模型选择)

机器学习系列之机器学习之Logistic回归(逻辑蒂斯回归)

相关文章
|
3天前
|
Python
探索Python中的装饰器:简化代码,增强功能
【9月更文挑战第3天】在Python的世界里,装饰器是那些静悄悄站在角落、却能大大改变游戏规则的神奇工具。它们就像是给你的函数穿上一件隐形的超级英雄斗篷,让函数拥有了超乎寻常的能力。本文将带领你一探究竟,看看如何通过几行简单的代码,就能让你的函数变得更加智能和强大。
|
3天前
|
Python
Python中的装饰器:简化你的代码
【9月更文挑战第3天】装饰器,这个听起来有些神秘的名词,实际上在Python中扮演着重要的角色。它们就像是你的代码的小助手,帮你自动完成一些重复性的工作,让你的代码更加简洁、易读。本文将通过一个简单的例子,带你走进装饰器的世界,看看它们是如何工作的。
|
3天前
|
测试技术 数据安全/隐私保护 Python
Python中的装饰器:简化你的代码
【9月更文挑战第3天】装饰器在Python中是一个非常强大的工具,它可以让我们在不改变原有函数定义的情况下,对函数进行扩展,增加额外的功能。本文将通过一个简单的例子,介绍如何在Python中使用装饰器,以及如何使用装饰器来简化我们的代码。
11 6
|
2天前
|
缓存 数据挖掘 Python
探索Python中的装饰器:简化代码,提高效率
【9月更文挑战第4天】在Python的世界里,装饰器是那些隐藏在幕后、默默发挥作用的英雄。它们以优雅的姿态简化我们的代码,提升程序的可读性和效率。本文将带你揭开装饰器的神秘面纱,通过实际案例展示其魅力所在,让你的编程之旅更加顺畅。
|
2天前
|
存储 Python
Python编程入门:从零开始的代码之旅
【9月更文挑战第4天】本文将带领初学者步入Python的世界,通过简明的语言和直观的例子,逐步揭示编程的乐趣。我们将一起构建基础的数据结构,探索控制语句的奥秘,并实现简单的函数。无论你是编程新手还是希望巩固基础,这篇文章都是你理想的起点。让我们开始吧,一步步将代码块搭建成思维的宫殿!
14 2
|
3天前
|
存储 设计模式 缓存
Python中的装饰器:简化代码,提高可读性
【9月更文挑战第3天】在Python编程中,装饰器是一种强大的工具,它允许我们修改或增强函数的行为,而无需更改其源代码。通过本文,您将了解装饰器的基本概念、如何创建和使用它们,以及它们如何帮助我们编写更简洁、更可读的代码。我们将以一个简单的示例开始,逐步深入到更复杂的应用场景,展示装饰器的灵活性和强大功能。无论您是初学者还是有经验的开发者,本文都将为您提供新的视角和技巧,让您的Python代码更加优雅和高效。
|
5天前
|
存储 缓存 分布式计算
|
7天前
|
Python
探索Python装饰器:简化代码,提升效率
【8月更文挑战第31天】装饰器在Python中是一种强大的工具,它允许我们在不修改函数代码的情况下增加额外的功能。本文将通过实际例子和简单易懂的语言,带你了解什么是装饰器、如何创建和使用它们,以及装饰器如何帮助我们编写更加简洁高效的代码。我们将从基础开始,逐步深入到装饰器的高级应用,让你轻松掌握这一实用的编程技巧。
|
7天前
|
算法 Python
揭秘Python编程之美:从代码到艺术的转变
【9月更文挑战第1天】 在这篇文章中,我们将一起探索如何将看似枯燥的Python编程代码转变为一门充满创造性和美感的艺术。通过深入浅出的解释、生动的例子和实用的技巧,你将学会如何编写更加优雅、高效且易于理解的Python代码,从而提升你的编程技能并享受编程的乐趣。
13 2
|
5天前
|
测试技术 Python
探索Python中的装饰器:简化代码,增强功能
【9月更文挑战第2天】本文将带你深入理解Python中强大的工具——装饰器。我们将一步步从基础定义到实际应用,展示如何利用装饰器简化代码结构,增加函数功能,而无需修改原有代码。通过具体例子,你将学会创建自定义装饰器,以及如何在实际项目中有效使用它们。让我们一起开启这段简化与增强的旅程吧!
下一篇
DDNS