决策数应该是那些对人工智能/专家系统了解不深的人的最初认知吧,各种if-then的强逻辑关系来让计算机具备人脑一样的决策力。说起来似乎挺简单的,找行业专家把他的经验都写下来,然后找人开始写if-then语句blablabla。但是人脑的经验决策一定对吗?人脑的决策思路真的没问题吗?抛开工作量,真的将一堆if-then放进计算机就是人工智能?
这些问题时不时会出现在我的脑海里,让我去思考,在我这一路人工智能进阶的路上,对于A.I.,对于专家系统,我的理解逐渐变化,对上述的几个问题,也逐渐懂得了如何去回答。
首先,if-then的说法是一个没毛病的策略,买车买房子等等生活中所有需要做出选择的场景,if-then是每个人思考的核心逻辑。但是决策树算法并非那样简单,算法工程师需要思考的是将所有的判断进行最优化排序,让对结果影响大的决策优先进行判断,按照强度顺序依次判断分类,到最终得到结果。这一步的逻辑是行外人所不知的,现实生活中,我们思考问题都有权重之分,我们去买车,选择面太广了,日本车,美国车,德国车,豪跑,SUV,四驱,两驱,颜色,内室设计等等,我们人脑的运算能力有限,一提出这些问题,我们就头大,这是很普遍的问题,因为我们没法一次性得出我们想找的答案,我们只能和家里人商量,“我们究竟最关注什么?”,对我来说,我喜欢SUV,那么我首选SUV,这样大量的轿车跑车就会被排除,然后,我比较看重车牌的原产地,我喜欢美系车,没有理由,因此,日本车德国车国产车等等就都排除出去,现在剩下的选择就少很多了,这个思路是我们人脑在先天运算能力有限的情况下,我们的思考方法,当我们的思考面不够宽广,也许我们会得到一些错误的答案。这也就是目前人工智能需要避免并且有能力避免的问题。
人工智能的前提是数据挖掘,完整的数据挖掘体系可以为人工智能提供良好的数据基础。这一点,所谓的行业专家就变得不那么“专家”了。数据挖掘可以在大量的数据里找出问题,而这些问题有可能是专家预见的,有可能是非预见的,人工智能促进专家去思考,而专家以判断的形式反哺人工智能,这是主辅关系不停轮换,也是一种积极的学习模式。
扯远了,回过头来,决策树就是要用历史数据来找出对结果影响最大的特征,而并非专家的经验,经验可以骗人,但是完整的数据不会。如果将单一的专家经验通过if-then注入计算机,那不是人工智能,那是伪人工智能,他的能力太有限了,就像那个专家一样。更有意思的是,如果专家的逻辑有问题,理解有误,那就不是人工智能,那就是人工智障了。
说了这么多,其实是为了将决策树和传统意义的if-then分开,决策树的能力远远强于我们字面对他的理解。接下类就重点说说决策树的算法和功能。
决策树的概念
决策树(Decision Tree)是一种基本的分类与回归方法。可以做分类问题,也可以做回归问题。他的优点是他的树形构架是通过if-then实现,因此做分类时结果的可读性可理解性都很强。但是决策树的缺点也很明显,就是容易出现过拟合的问题。在决策树模型在学习时,利用训练数据,根据损失函数最小的原则建立决策树模型。回归问题和回归问题的损失函数不同。
决策树的步骤
特征选择,决策树的生成,决策树的修剪。
决策树的分类思路
用决策树分类:从根节点开始,对实例的某一个特征进行测试,根据测试结果将实例分配到其子节点,此时每个子节点对应着该特征的一个取值,递归对实例进行测试并分配,直到到达叶节点,最后将实例分到叶节点的类中,分类结束。
- 决策树每通过一个节点都需要选择一次最优特征,然后按照这个特征进行分割子集。
- 如果子集已经被基本正确分类,那么就需要构建叶节点,叶节点为终止节点。
- 如果每个子集都被分到叶节点上,即都有了明确的类,这时决策树就生成了。
决策树在分类过程中特征选择的依据
-
信息熵&信息增益
信息熵定义: 字面意思上的理解就是描述一个信息不确定度的标量。信息熵越大,表示该信息不确定度越大,信息熵越小,表示该信息不确定性越小。
, 样本k的经验概率
, 有k个类别,样本总数为D,某类别的样本个数。
信息增益:根据某特征分类前后,信息不确定性发生的变化。表示得知特征X的信息而使得类Y的信息不确定性减少的程度。决策树中我们优先选取信息增益最大的特征进行分类。
信息增益比:从信息增益中,可以看出,信息增益的大小取决于数据集的经验熵,经验熵大的时候,信息增益会偏大,反之,信息增益会减小。特征取值越多,信息增益便会偏大。信息增益比会对这个问题进行矫正。
缺点:当特征取值较少时,取值越小,那么信息增益比就会越大,因此,信息增益比倾向于取值较少的特征。
综上,在使用信息增益比的时候,应该是先选择信息增益高于平均水平的特征,然后在这些特征中再选择信息增益率最高的特征。
-
gini指数
定义:表示在样本集合中一个随机选中的样本被分错的概率。gini指数越小表示集合被选中的样本被分错的概率越小,也就是说集合的纯度越高,反之,集合越不纯。
表示样本属于K类别的概率,表示样本不属于K类别的概率。
样本集合D的gini指数:
上代码,在代码里理解这些变量。
数据集
def createDataSet():
# 数据集
dataSet=[[0, 0, 0, 0, 'no'],
[0, 0, 0, 1, 'no'],
[0, 1, 0, 1, 'yes'],
[0, 1, 1, 0, 'yes'],
[0, 0, 0, 0, 'no'],
[1, 0, 0, 0, 'no'],
[1, 0, 0, 1, 'no'],
[1, 1, 1, 1, 'yes'],
[1, 0, 1, 2, 'yes'],
[1, 0, 1, 2, 'yes'],
[2, 0, 1, 2, 'yes'],
[2, 0, 1, 1, 'yes'],
[2, 1, 0, 1, 'yes'],
[2, 1, 0, 2, 'yes'],
[2, 0, 0, 0, 'no']]
#分类属性
labels=['年龄','有工作','有自己的房子','信贷情况']
#返回数据集和分类属性
return dataSet,labels
import numpy as np
def entropyCalculate(dataSet):
numData = len(dataSet)
labelCount={}
for row in dataSet:
label = row[-1]
if label not in labelCount.keys():
labelCount[label] = 0
labelCount[label] += 1
entropy = 0
for key in labelCount:
prob = float(labelCount[key])/numData
entropy = entropy - prob*np.log2(prob)
return(entropy)
def featureSelection(dataSet):
#dataSet实际上是每一层的数据
numFeature = len(dataSet[0])-1
dataEntropy = entropyCalculate(dataSet)
largestgain = 0
for i in range(numFeature):
featureList = [data[i] for data in dataSet]
featureValue = set(featureList)
conditionEntropy = 0
for value in featureValue:
subdataSet = regroupData(dataSet, i, value)
prob = len(subdataSet)/float(len(dataSet))
conditionEntropy += prob * entropyCalculate(subdataSet)
inforgain = dataEntropy - conditionEntropy
print('第%d个特征的增益为%.3f' %(i, inforgain))
if (inforgain > largestgain):
largestgain = inforgain
bestFeature = i
return(bestFeature)
#axis代表特征index, value代表特征某一个变量
def regroupData(dataSet, axis, value):
dataSetNew=[]
for data in dataSet:
if data[axis] == value:
midvalue = data[:axis]
midvalue.extend(data[axis+1:])
dataSetNew.append(midvalue)
return(dataSetNew)
#构建决策树
def createTree(dataSet, labels, featLabels):
#首先分析数据标签,如果标签一致,就停止分类,如果标签不一致,继续下面的决策树分类
classList = [example[-1] for example in dataSet]
if classList.count(classList[0]) == len(classList):
return(classList[0])
#选择最优特征
bestFeat = featureSelection(dataSet)
#定位最优特征的标签
bestFeatLabel=labels[bestFeat]
featLabels.append(bestFeatLabel)
#生成树
myTree={bestFeatLabel:{}}
#删除已经使用的特征标签
del(labels[bestFeat])
#找最有特征的属性
featValues = [example[bestFeat] for example in dataSet]
#去掉重复属性
uniqueVls = set(featValues)
for value in uniqueVls:
myTree[bestFeatLabel][value]=createTree(regroupData(dataSet,bestFeat,value),labels,featLabels)
return(myTree)
featLabels=[]
myTree=createTree(dataSet,labels,featLabels)
print(myTree)
决策树是一个不断迭代的过程,直到数据属于同一类,程序终止。