人工智能学习(三)

一、什么是决策树

决策树是一种机器学习的方法。决策树的生成算法有ID3, C4.5和C5.0等。决策树是一种树形结构,其中每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出,最后每个叶节点代表一种分类结果。

对于复杂的预测问题,通过建立树模型产生分支节点,被划分成两个(二叉树)或多个(多叉树)较为简单的子集,从结构上划分为不同的子问题。将依规则分割数据集的过程不断递归下去。

随着树的深度不断增加,分支节点的子集越来越小,所需要提的问题数也逐渐简化。当分支节点的深度或者问题的简单程度满足一定的停止规则时, 该分支节点会停止分裂,此为自上而下的停止阈值法;有些决策树也使用自下而上的剪枝法。

二、ID3算法

1、ID3

ID3算法是决策树的一种,它是基于奥卡姆剃刀原理的,即用尽量用较少的东西做更多的事。ID3算法,即Iterative Dichotomiser 3,迭代二叉树3代,是Ross Quinlan发明的一种决策树算法,这个算法的基础就是上面提到的奥卡姆剃刀原理,越是小型的决策树越优于大的决策树,尽管如此,也不总是生成最小的树型结构,而是一个启发式算法。

2、信息熵

熵这个概念最早起源于物理学,在物理学中是用来度量一个热力学系统的无序程度,而在信息学里面,熵是对不确定性的度量。在1948年,香农引入了信息熵,将其定义为离散随机事件出现的概率,一个系统越是有序,信息熵就越低,反之一个系统越是混乱,它的信息熵就越高。所以信息熵可以被认为是系统有序化程度的一个度量。

假如一个随机变量X的取值为:
在这里插入图片描述
每一种取到的概率分别是:
在这里插入图片描述
那么X的熵定义为:
在这里插入图片描述

对于分类系统来说,类别C是变量,它的取值为:
在这里插入图片描述

而每一个类别出现的概率分别是:
在这里插入图片描述
而这里的n就是类别的总数,此时分类系统的熵就可以表示为:
在这里插入图片描述

3、信息增益、

信息增益是针对一个一个特征而言的,就是看一个特征T,系统有它和没有它时的信息量各是多少,两者的差值就是这个特征给系统带来的信息量,即信息增益。

三、挑选西瓜

在excel中构建如下的数据集
在这里插入图片描述
Python代码如下:

import pandas as pd
import numpy as np
from collections import Counter
from math import log2

#数据获取与处理
def getData(filePath):
    data = pd.read_excel(filePath)
    return data

def dataDeal(data):
    dataList = np.array(data).tolist()
    dataSet = [element[1:] for element in dataList]
    return dataSet
    
    #获取属性名称
def getLabels(data):
    labels = list(data.columns)[1:-1]
    return labels
    
    #获取类别标记
def targetClass(dataSet):
    classification = set([element[-1] for element in dataSet])
    return classification
    
    #将分支结点标记为叶结点,选择样本数最多的类作为类标记
def majorityRule(dataSet):
    mostKind = Counter([element[-1] for element in dataSet]).most_common(1)
    majorityKind = mostKind[0][0]
    return majorityKind
    
    #计算信息熵
def infoEntropy(dataSet):
    classColumnCnt = Counter([element[-1] for element in dataSet])
    Ent = 0
    for symbol in classColumnCnt:
        p_k = classColumnCnt[symbol]/len(dataSet)
        Ent = Ent-p_k*log2(p_k)
    return Ent
    
    #子数据集构建
def makeAttributeData(dataSet,value,iColumn):
    attributeData = []
    for element in dataSet:
        if element[iColumn]==value:
            row = element[:iColumn]
            row.extend(element[iColumn+1:])
            attributeData.append(row)
    return attributeData
    
    #计算信息增益
def infoGain(dataSet,iColumn):
    Ent = infoEntropy(dataSet)
    tempGain = 0.0
    attribute = set([element[iColumn] for element in dataSet])
    for value in attribute:
        attributeData = makeAttributeData(dataSet,value,iColumn)
        tempGain = tempGain+len(attributeData)/len(dataSet)*infoEntropy(attributeData)
        Gain = Ent-tempGain
    return Gain
    
    #选择最优属性                
def selectOptimalAttribute(dataSet,labels):
    bestGain = 0
    sequence = 0
    for iColumn in range(0,len(labels)):#不计最后的类别列
        Gain = infoGain(dataSet,iColumn)
        if Gain>bestGain:
            bestGain = Gain
            sequence = iColumn
        print(labels[iColumn],Gain)
    return sequence
    
    #建立决策树
def createTree(dataSet,labels):
    classification = targetClass(dataSet) #获取类别种类(集合去重)
    if len(classification) == 1:
        return list(classification)[0]
    if len(labels) == 1:
        return majorityRule(dataSet)#返回样本种类较多的类别
    sequence = selectOptimalAttribute(dataSet,labels)
    print(labels)
    optimalAttribute = labels[sequence]
    del(labels[sequence])
    myTree = {optimalAttribute:{}}
    attribute = set([element[sequence] for element in dataSet])
    for value in attribute:
        
        print(myTree)
        print(value)
        subLabels = labels[:]
        myTree[optimalAttribute][value] =  \
                createTree(makeAttributeData(dataSet,value,sequence),subLabels)
    return myTree
    
def main():
    filePath = 'D:\watermelondata.xls'
    data = getData(filePath)
    dataSet = dataDeal(data)
    labels = getLabels(data)
    myTree = createTree(dataSet,labels)
    return myTree
    
if __name__ == '__main__':
    myTree = main()

结果如下:

色泽 0.10812516526536531
根蒂 0.14267495956679277
敲声 0.14078143361499584
纹理 0.3805918973682686
脐部 0.28915878284167895
触感 0.006046489176565584
['色泽', '根蒂', '敲声', '纹理', '脐部', '触感']
{'纹理': {}}
稍糊
色泽 0.3219280948873623
根蒂 0.07290559532005603
敲声 0.3219280948873623
脐部 0.17095059445466865
触感 0.7219280948873623
['色泽', '根蒂', '敲声', '脐部', '触感']
{'触感': {}}
硬滑
{'触感': {'硬滑': '否'}}
软粘
{'纹理': {'稍糊': {'触感': {'硬滑': '否', '软粘': '是'}}}}
清晰
色泽 0.04306839587828004
根蒂 0.45810589515712374
敲声 0.33085622540971754
脐部 0.45810589515712374
触感 0.45810589515712374
['色泽', '根蒂', '敲声', '脐部', '触感']
{'根蒂': {}}
硬挺
{'根蒂': {'硬挺': '否'}}
蜷缩
{'根蒂': {'硬挺': '否', '蜷缩': '是'}}
稍蜷
色泽 0.2516291673878229
敲声 0.0
脐部 0.0
触感 0.2516291673878229
['色泽', '敲声', '脐部', '触感']
{'色泽': {}}
青绿
{'色泽': {'青绿': '是'}}
乌黑
敲声 0.0
脐部 0.0
触感 1.0
['敲声', '脐部', '触感']
{'触感': {}}
硬滑
{'触感': {'硬滑': '是'}}
软粘
{'纹理': {'稍糊': {'触感': {'硬滑': '否', '软粘': '是'}}, '清晰': {'根蒂': {'硬挺': '否', '蜷缩': '是', '稍蜷': {'色泽': {'青绿': '是', '乌黑': {'触感': {'硬滑': '是', '软粘': '否'}}}}}}}}
模糊

四、用sk-learn库对西瓜数据集,分别进行ID3、C4.5和CART的算法代码实现

1.ID3

创建如图的数据集
在这里插入图片描述

import pandas as pd
import graphviz 
from sklearn.model_selection import train_test_split
from sklearn import tree

f = open('D:\watermelondata.csv',encoding='utf-8')
data = pd.read_csv(f)

x = data[["色泽","根蒂","敲声","纹理","脐部","触感"]].copy()
y = data['好瓜'].copy()
print(data)
#将特征值数值化
x = x.copy()
for i in ["色泽","根蒂","敲声","纹理","脐部","触感"]:
    for j in range(len(x)):
        if(x[i][j] == "青绿" or x[i][j] == "蜷缩" or data[i][j] == "浊响" \
           or x[i][j] == "清晰" or x[i][j] == "凹陷" or x[i][j] == "硬滑"):
            x[i][j] = 1
        elif(x[i][j] == "乌黑" or x[i][j] == "稍蜷" or data[i][j] == "沉闷" \
           or x[i][j] == "稍糊" or x[i][j] == "稍凹" or x[i][j] == "软粘"):
            x[i][j] = 2
        else:
            x[i][j] = 3
            
y = y.copy()
for i in range(len(y)):
    if(y[i] == "是"):
        y[i] = int(1)
    else:
        y[i] = int(-1) 
#需要将数据x,y转化好格式,数据框dataframe,否则格式报错
x = pd.DataFrame(x).astype(int)
y = pd.DataFrame(y).astype(int)
print(x)
print(y)

x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.2)
print(x_train)

#决策树学习
clf = tree.DecisionTreeClassifier(criterion="entropy")                    #实例化 
clf = clf.fit(x_train, y_train) 
score = clf.score(x_test, y_test)
print(score)

选择“根蒂",“敲声”,“纹理”,“脐部”,"触感”进行训练
在这里插入图片描述

2.C4.5

(1)ID3的缺陷

对于ID3算法,它存在以下问题:

  • 取值多的属性,更容易使数据更纯,其信息增益更大;
  • 训练得到的是一棵庞大且深度浅的树,这样的树是不合理的。

C4.5算法可以抑制ID3的上述缺点。

(2)C4.5算法

C4.5算法是由Ross Quinlan开发的用于产生决策树的算法。该算法是对Ross
Quinlan之前开发的ID3算法的一个扩展。C4.5算法产生的决策树可以被用作分类目的,因此该算法也可以用于统计分类。其通过信息增益比来进行特征选择。

(3)信息增益率

假如某个条件极其严格,比如某个同学提前知道了所有选题的答案,那么将选题的序号作为条件,不存在任何不确定性,所以可以得到最大的信息增益。但是这个条件是没有意义的,假设老师换一份考卷答案就全部作废了。

信息增益率在信息增益的基础上增加了惩罚项,惩罚项是特征的固有值,是避免上述情况而设计的。

写作 gr(X,Y)。定义为信息增益除以特征的固有值,如下
在这里插入图片描述
继续以单项选择题为例,通过分析选题的长短特征之后,信息增益g(X,Y)为2bit,惩罚项H(Y)=-0.1log0.1-0.1log0.1-0.8*log0.8=0.92

信息增益率为0.4/0.92=43%,其中,信息增益率为43%。

3.CART算符

(1)CART

CART是一棵二叉树,每一次分裂会产生两个子节点。CART树分为分类树和回归树。

分类树主要针对目标标量为分类变量,比如预测一个动物是否是哺乳动物。

回归树针对目标变量为连续值的情况,比如预测一个动物的年龄。

如果是分类树,将选择能够最小化分裂后节点GINI值的分裂属性;

如果是回归树,选择能够最小化两个节点样本方差的分裂属性。CART跟其他决策树算法一样,需要进行剪枝,才能防止算法过拟合从而保证算法的泛化性能。

(2)基尼指数

CART决策树算法使用基尼指数来选择划分属性,基尼指数定义为:

          Gini(D) = ∑k=1 ∑k'≠1 pk·pk' = 1- ∑k=1  pk·pk

可以这样理解基尼指数:从数据集D中随机抽取两个样本,其类别标记不一致的概率。Gini(D)越小,纯度越高。

属性a的基尼指数定义:

      Gain_index(D,a) = ∑v=1 |Dv|/|D|·Gini(Dv)

使用基尼指数选择最优划分属性,即选择使得划分后基尼指数最小的属性作为最优划分属性。

总结

本次实验的主要目的是了解以及熟悉分别在不使用sk-learn和使用sk-learn的情况下用ID3算法进行一个简单的机器学习。同时对C4.5算法和CART算法进行一个了解。

参考文章

https://blog.csdn.net/weixin_56102526/article/details/120987844?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_45659777/article/details/120960616?spm=1001.2014.3001.5501

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值