决策树3:基尼指数--Gini index(CART)

原理:

在这里插入图片描述既能做分类,又能做回归。
分类:基尼值作为节点分类依据。
回归:最小方差作为节点的依据。

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述节点越不纯,基尼值越大,熵值越大
在这里插入图片描述在这里插入图片描述方差越小越好。
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述总体的基尼值:0.343
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述## 代码实践

#整个c4.5决策树的所有算法:
import numpy as np
import operator

def creatDataSet():
    """
    outlook-> 0:sunny | 1:overcast | 2:rain
    temperature-> 0:hot | 1:mild | 2:cool
    humidity-> 0:high | 1:normal
    windy-> 0:false | 1:true
    """
    dataSet = np.array([[0, 0, 0, 0, 'N'],
               [0, 0, 0, 1, 'N'],
               [1, 0, 0, 0, 'Y'],
               [2, 1, 0, 0, 'Y'],
               [2, 2, 1, 0, 'Y'],
               [2, 2, 1, 1, 'N'],
               [1, 2, 1, 1, 'Y']])
    labels = np.array(['outlook', 'temperature', 'humidity', 'windy'])
    return dataSet, labels


def createTestSet():
    """
    outlook-> 0:sunny | 1:overcast | 2:rain
    temperature-> 0:hot | 1:mild | 2:cool
    humidity-> 0:high | 1:normal
    windy-> 0:false | 1:true
    """
    testSet = np.array([[0, 1, 0, 0],
               [0, 2, 1, 0],
               [2, 1, 1, 0],
               [0, 1, 1, 1],
               [1, 1, 0, 1],
               [1, 0, 1, 0],
               [2, 1, 0, 1]])
    return testSet

def dataset_entropy(dataset):
    """
    计算数据集的信息熵
    """
    classLabel=dataset[:,-1]
    labelCount={}
    for i in range(classLabel.size):
        label=classLabel[i]
        labelCount[label]=labelCount.get(label,0)+1     #将所有的类别都计算出来了
    #熵值(第一步)
    cnt=0
    for k,v in labelCount.items():
        cnt += -v/classLabel.size*np.log2(v/classLabel.size)
    
    return cnt

    #接下来切分,然后算最优属性
def splitDataSet(dataset,featureIndex,value):
    subdataset=[]
    #迭代所有的样本
    for example in dataset:
        if example[featureIndex]==value:
            subdataset.append(example)
    return np.delete(subdataset,featureIndex,axis=1)

def classLabelPi(dataset):
    #多叉树
    classLabel=dataset[:,-1]
    labelCount={}
    for i in range(classLabel.size):
        label=classLabel[i]
        labelCount[label]=labelCount.get(label,0)+1
    valueList=list(labelCount.values())
    sum=np.sum(valueList)
    pi=0
    for i in valueList:
        pi+=(i/sum)**2
    return pi

def chooseBestFeature(dataset,labels):
    """
    选择最优特征,但是特征是不包括名称的。
    如何选择最优特征:增益率最小
    """
    #特征的个数
    featureNum=labels.size
    baseEntropy=dataset_entropy(dataset)
    #设置最大增益值
    maxRatio,bestFeatureIndex=0,None
    #样本总数
    n=dataset.shape[0] 
    #最小基尼值 
    minGini=1
    for i in range(featureNum):
        #指定特征的条件熵
        featureEntropy=0
        gini=0
        #返回所有子集
        featureList=dataset[:,i]
        featureValues=set(featureList)
        for value in featureValues:
            subDataSet=splitDataSet(dataset,i,value) 
            pi=subDataSet.shape[0]/n 
            gini+=pi*(1-classLabelPi(subDataSet))  
        if minGini > gini:
            minGini=gini
            bestFeatureIndex=i
    return bestFeatureIndex #最佳增益

def mayorClass(classList):
    labelCount={}
    for i in range(classList.size):
        label=classList[i]
        labelCount[label]=labelCount.get(label,0)+1
    sortedLabel=sorted(labelCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedLabel[0][0]

def createTree(dataset,labels):
    """
    参考hunt算法那张图片
    """
    classList=dataset[:,-1]
    if len(set(dataset[:,-1]))==1:
        return dataset[:,-1][0] #返回类别
    if labels.size==0 or len(dataset[0])==1:  #条件熵最少的一定是类别最多的
        #条件熵算不下去的时候,
        return mayorClass(classList)
    bestFeatureIndex=chooseBestFeature(dataset,labels)
    bestFeature=labels[bestFeatureIndex]
    dtree={bestFeature:{}}  #用代码表示这棵树
    featureList=dataset[:,bestFeatureIndex]
    featureValues=set(featureList)
    for value in featureValues:
        subdataset=splitDataSet(dataset,bestFeatureIndex,value)
        sublabels=np.delete(labels,bestFeatureIndex)
        dtree[bestFeature][value]=createTree(subdataset,sublabels) #将原始的labels干掉一列
    return dtree

def predict(tree,labels,testData):
    #分类,预测
    rootName=list(tree.keys())[0]
    rootValue=tree[rootName]
    featureIndex =list(labels).index(rootName)
    classLabel=None 
    for key in rootValue.keys():
        if testData[featureIndex]==int(key):
            if type(rootValue[key]).__name__=="dict":
                classLabel=predict(rootValue[key],labels,testData)    #递归
            else:
                classLabel=rootValue[key]
    return classLabel

def predictAll(tree,labels,testSet):
    classLabels=[]
    for i in testSet:
        classLabels.append(predict(tree,labels,i))
    return classLabels

if __name__ == "__main__":
    dataset,labels=creatDataSet()
    # print(dataset_entropy(dataset)
    # s=splitDataSet(dataset,0)
    # for item in s:
    #     print(item)
    tree=createTree(dataset,labels)
    testSet=createTestSet()
    print(predictAll(tree,labels,testSet))
····························································
输出:
['N', 'N', 'Y', 'N', 'Y', 'Y', 'N']

补充:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
记住公式!!!

  • 19
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AppleYRY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值