介绍Python使用决策树进行机器学习
对机器学习的简短介绍
机器学习算法可以大致分为以下类别
分类:这种类型的算法可以将输入分类为输出类之一。一个非常简单的例子就是手写字母识别。给定输入的字母表图像,分类算法可以将图像分类为英文字母之一,即A ... Z之一。
回归:这种算法产生连续的数值。例如,取决于与该人相关的各种参数的人的医疗保险费。
强化学习:这是从经验中学习。在这种类型中,学习代理尝试不同的方式来达到目标,并最终学习如何达到目标。例如,一个机器人试图到达房间的特定角落,因为房间里有一些随机障碍物。
聚类或分组:这种算法可以将输入数据集合成几组相似的数据。例如,给定一组衣服图像,聚类算法可以将衬衫,裤子,裙子等分组在一起。
分类和回归属于监督学习算法。在这种算法中,有一组标记数据,即为每个输入指定输出的一组数据。然后这些数据经过一个训练过程,这个过程产生了输入和输出之间的关系。一旦我们与我们有关系,我们可以预测任何不可预见的输入数据的输出。
聚类属于无监督学习算法。在这种情况下,没有可用于输入数据的标签。原始数据根据相似性聚类或组合在一起。
增强学习算法是有监督和无监督学习算法的混合。
决策树
这是一个监督学习算法。
这里我将详细讨论决策树的概念和实现。
1)它可以执行分类和回归。
2)计算成本相当低。
3)易于理解。
4)训练好的模型可以可视化,不像神经网络似乎是一个黑匣子。
由于这些原因,最近几天决策树越来越受欢迎。
决策树的直观解释
假设一个学生今天不太确定如何度过这个晚上。她可以去参加聚会或酒吧,可以学习或看电影。对于做什么感到困惑,她提到了一个可供她使用的决策树。
现在,她很容易决定如何度过这个晚上。如果在某个地方举办派对,那肯定会参加。如果不是,则查找其他选项和约束。
现在,如何构建这个决策树。
决策树可以基于旧的历史数据建立。在我们继续研究如何构建决策树之前,让我们快速了解信息和熵。
信息(Information)
如何衡量信息?信息是根据事件的不确定性来衡量的。
事件的信息内容使用以下等式进行量化
Information(I)= -log(P)其中'P'是发生事件的概率。
这个方程捕捉事件的不确定性。事件越不确定(发生概率越小),其信息内容就越高。
例如“明天太阳升起”的声明没有任何信息。由于明天的日出概率为1,因此信息内容为-log(1)=0。另一方面,在一个夏天的某天声明“今天将下雨”,有更多的Information,因为下雨在夏天的机会较少发生。
信息熵
熵就是随机事件信息的平均(预期)量,并由以下等式给出
Entropy =-ΣPi* log(Pi)
举个例子,我们考虑一个有4个红球,2个黄球和3个绿球的盒子。
从箱子中选择一个球有三种可能性 - 红色,绿色或蓝色,并具有以下概率
红球= 4/9
绿球= 3/9
黄球= 2/9
因此,熵= - [(4/9)* log(4/9)+(3/9)* log(3/9)+(2/9)* log(2/9)] = 1.5304755
因此,每次您从包装箱中选择一个球时,您都会收到1.5304755个信息。
现在,考虑到盒子只包含一种类型的球,例如红色,那么以下将是选择特定颜色的球的可能性
红球= 9/9 = 1
绿球= 0/9 = 0
黄球= 0/9 = 0
因此,熵= [1 * log(1)+ 0 * log(0)+ 0 * log(0)] = 0。
这意味着你每次选择球时都会得到零信息。因为你知道它肯定会是一个红球,并且没有不确定性。
简而言之,熵给出了数据集中不确定性或方差或无序或混沌的指示。
构建决策树
假设我们有以下数据可供我们使用,并且我们想从中构建决策树。
这里,前三列是特征,最后一列是特征组合的输出类。
决策树是以贪婪的方式构建的,从根开始,在每一步选择最有用的功能。在每个步骤中,选择一个属性/特征来对数据集进行拆分。选择具有最低熵的特征,因为低熵意味着数据无序(大多数数据几乎相似)。因此,选择这样的功能进行拆分,会生成具有相似或同类数据的分支。
一旦数据在功能上被分割,在接下来的步骤中,就会考虑其余功能。在完成树之前,一直遵循相同的步骤。
在我们的例子中,我们有三个特征, “Deadline”, “Is there a party” 和“lazy”。我们将计算所有这三个特征的熵,并选择一个熵最低的特征。
我们将详细介绍如何计算特征“Is there a party”的熵。
最左边的表格显示“Is there a party”列及其相应的输出。中间显示“Is there a party”的输出是“No”,而最右边的表显示“Is there a party”时的输出是“Yes”。
“Is there a party” 为No的熵计算:
Study的概率= 3/5
Pub的概率= 1/5
Tv的概率= 1/5
熵(“Is there a party”,No)= - [(3/5)* log(3/5)+(1/5)* log(1/5)+(1/5)* log(1 / 5)]= 1.371
“Is there a party” 为Yes的熵计算:
Party的可能性= 5/5 = 1
熵(“Is there a party”,Yes)= - [1 * log(1)] = 0
在这种情况下熵出现为零,因为所有数据都是相同的,并且数据没有差异。
现在让我们来计算熵的特征“Is there a party”
权重Yes = 5/10
权重No = 5/10
所以,“Is there a party”的特征的平均熵如下:
熵(Is there a party)=(Yes的权重)*熵(“Is there a party”,Yes)+(No的权重)*熵(“Is there a party”,No)=(5/10)* 0 +(5/10)* 1.371 = 0.6855
熵(Deadline)= 1.151
熵(lazy)= 1.4755
所以我们会选择最均匀或者更少的混沌特征(即最小熵值),这就是“Is there a party”,现在决策树会看起来像下面那样,
树的左侧不能进一步分割,因为在这种情况下,熵是0(数据和纯数据没有差异),只剩下一个选择 - 去聚会。但是右侧分支可以进一步分裂,因为它不是纯粹的。
在下一步中,我们有一个简化的数据集,如下所示
按照与以前相同的流程对这个缩小的数据集进行处理,
熵(Deadline)= 0.4
熵(lazy)= 1.2
所以,我们在这种情况下选择Deadline,这导致我们到了下面的树
按照相同的步骤将导致我们完成树如下:
Gini impurity
与熵相似,Gini impurity是生成同质分支的另一种方式。这种技术不在这里讨论。
使用sci kit学习实现决策树
使用决策树分类
到目前为止,我们已经形成了一个决策树如何工作的想法 真正的实现可能并不遵循我们已经讨论过的完全相同的过程,而是一个完善的过程。但基本的想法依然如此。
我们将看到使用Scikit学习的DecisionTreeClassifier进行分类的例子。我们将提供我们在前面部分中使用的相同数据。
from enum import Enum
import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_graphviz
from sklearn.datasets import load_iris
feature_names = ['Deadline', 'is There a party', 'Lazy']
target_names = ['Party', 'Study', 'Go to pub', 'Watch TV']
class Deadline(Enum):
URGENT = 1
NEAR = 2
NONE = 3
class IsThereAParty(Enum):
YES = 1
NO = 2
class Lazy(Enum):
YES = 1
NO = 2
class Activity(Enum):
PARTY = 1
STUDY = 2
PUB = 3
TV = 4
def getFeatureTrainingData():
featureData = np.matrix([
[Deadline.URGENT.value, IsThereAParty.NO.value, Lazy.YES.value],
[Deadline.URGENT.value, IsThereAParty.NO.value, Lazy.YES.value],
[Deadline.NEAR.value, IsThereAParty.YES.value, Lazy.YES.value],
[Deadline.NONE.value, IsThereAParty.YES.value, Lazy.NO.value],
[Deadline.NONE.value, IsThereAParty.NO.value, Lazy.YES.value],
[Deadline.NONE.value, IsThereAParty.YES.value, Lazy.NO.value],
[Deadline.NEAR.value, IsThereAParty.NO.value, Lazy.NO.value],
[Deadline.NEAR.value, IsThereAParty.NO.value, Lazy.YES.value],
[Deadline.NEAR.value, IsThereAParty.YES.value, Lazy.YES.value],
[Deadline.URGENT.value, IsThereAParty.NO.value, Lazy.NO.value]
])
return featureData
def getOutputTrainingData():
outputData = [
Activity.PARTY.value,
Activity.STUDY.value,
Activity.PARTY.value,
Activity.PARTY.value,
Activity.PUB.value,
Activity.PARTY.value,
Activity.STUDY.value,
Activity.TV.value,
Activity.PARTY.value,
Activity.STUDY.value
]
return outputData
def decisionTreeClassifier():
# get training data set
x_train = getFeatureTrainingData()
y_train = getOutputTrainingData()
# Train decision tree classifier
tree_classifier = DecisionTreeClassifier(criterion="entropy", max_depth=5)
tree_classifier.fit(x_train, y_train)
# Predict for new data
prediction = tree_classifier.predict([[Deadline.URGENT.value, IsThereAParty.YES.value, Lazy.NO.value]])
print 'Predicted activity is following'
print(Activity(prediction).name)
# visualize the decision tree
export_graphviz(tree_classifier,
out_file='d.dot',
feature_names=feature_names,
class_names=target_names,
rounded=True,
filled=True)
decisionTreeClassifier()
上述代码将决策树导出到DecisionTree.dot文件,该文件可以使用graphviz软件包中的dot命令行工具转换为.png或.pdf文件
dot -Tpng DecisionTree.dot -o DecisionTree.png
以下是由上述代码生成的决策树的可视化。Scikit学习的DecisionTreeClassifier产生二叉树,因为它与我们的例子不完全匹配。
使用决策树进行回归
假设我们有以下数据代表基于个人年龄和工资收取的保险费。
我们希望对这些数据进行回归分析,以便我们可以预测在此数据集中不存在年龄和工资的个人所要支付的保险费
以下是使用scikit learn的DecisionTreeRegressor执行回归任务的示例。
import numpy as np
from sklearn.tree import DecisionTreeRegressor
def getFeatureTrainingData():
return np.matrix([
[30, 200],
[32, 355],
[12, 434],
[20, 484],
[65, 4545],
[45, 546],
[70, 44359],
[25, 120]
])
def getOutputTrainingData():
return [
45,
22,
43,
10,
16,
65,
100,
23
]
def decisionTreeRegression():
x_train = getFeatureTrainingData()
y_train = getOutputTrainingData()
tree_regression = DecisionTreeRegressor(max_depth=5)
tree_regression.fit(x_train, y_train)
prediction = tree_regression.predict([[21, 55]])
print 'following is the predicted insurance premium fro age 21 and salary 55'
print prediction[0]
decisionTreeRegression()