统计学习方法 | 决策树 | python实现

决策树的损失函数为正则化的极大似然函数。

根据一定的准则依次选择具有好的分类能力的特征,作为决策树的结点,将数据集划分为子集,继续选择最优特征,划分子集,一层层向下,直到子集已经更够被基本正确分类,构建叶结点。就生成了一棵决策树。

但这样可能会过拟合,需要剪枝。

特征选择有以下几种:信息增益

信息增益

在这里插入图片描述
经验熵的计算:

def cal_H_D(data):
    classes = set(data)
    H_D = 0
    for i in classes:
        p = data[data == i].size / data.size
        H_D += -1 * p * np.log2(p)
    return H_D

计算信息增益,当k=1时计算信息增益率

def gain(D, A, k=0):
    # D = np.array(D)
    # A = np.array(A)
    Aclasses = set(A)
    H_D_A = 0
    for i in Aclasses:
        H_D_A += A[A == i].size / A.size * cal_H_D(D[A == i])
    # k==1时表示信息增益率
    if k == 1:
        return 1 - H_D_A/cal_H_D(D)
    return cal_H_D(D) - H_D_A
决策树的生成

在这里插入图片描述

需要先写出选择D中实例最大的类别;选择信息增益最大的特征;将D分割为非空子集三个函数:

def mostInstance(self, label):
    if isinstance(label,list):
        return max(label, key=label.count)
    return max(label, key=label.tolist().count)

def selectFeature(self, data, A, k=0):
    data = np.array(data).T
    A = np.array(A)
    gains = [self.gain(item, A, k) for item in data]
    # print("gain:", gains)
    return np.argmax(np.array(gains)), max(gains)

def subset(self, data, label, I, ai):
    dataT = np.array(data).T
    label = np.array(label)
    temp = []
    for i in range(len(dataT)):
        temp.append(dataT[i][dataT[I] == ai])
    subdata = np.array(temp[:I] + temp[I+1:])
    sublabel = label[dataT[I] == ai]
    return subdata.T, sublabel

建树。将决策树保存在一个字典中。

def creat(self, data, label, k=0):
    epsilon = 0.01
    if len(set(label)) <= 1:
        return self.mostInstance(label)
    featureId, featureGain = self.selectFeature(data, label, k)
    # print("selected feature:",featureList[featureId])
    if featureGain < epsilon:
        return self.mostInstance(label)
    dataT = np.array(data).T
    tree = {}
    for ai in set(dataT[featureId]):
        subdata, sublabel = self.subset(data,label,featureId,ai)
        tree[str(featureId)+"|"+str(ai)] = self.creat(subdata,sublabel,k)
        # print(tree)
    return tree

预测:递归查找tree,返回对应的子结点来预测结果

def predict(self, tree, x):
    if isinstance(tree, dict):
        currentFeatureStr = list(tree.keys())
        currentFeaturt = currentFeatureStr[0].split("|")[0]
        return self.predict(tree[str(currentFeaturt)+"|"+str(x[int(currentFeaturt)])], x)
    return tree

对书中的例子运行如下

# 年龄,有工作,有自己的房子,信贷情况
example = [[1,0,0,1],[1,0,0,2],[1,1,0,2],[1,1,1,1],[1,0,0,1],
           [2,0,0,1],[2,0,0,2],[2,1,1,2],[2,0,1,3],[2,0,1,3],
           [3,0,1,3],[3,0,1,2],[3,1,0,2],[3,1,0,3],[3,0,0,1]]
labels = [0,0,1,1,0,0,0,1,1,1,1,1,1,1,0]
DT = DecisionTree()
Dtree = DT.creat(example, labels, 0)
print("Decision Tree:", Dtree)
print("[2,1,1,3] is class ", DT.predict(Dtree, [2,1,1,3]))

得到结果:

Decision Tree: {'2|0': {'1|0': 0, '1|1': 1}, '2|1': 1}
[2,1,1,3] is class  1

调用上面的算法时,k=1时便为C4.5算法。

剪枝问题:决策树的生成过程总是倾向于过拟合,需要通过剪枝来简化决策树,增强其泛化能力。可能以后准备好数据会写一下这部分代码(我太懒了qvq)

CART算法

CART算法用来解决输入变量为连续变量的问题,若输出变量为连续变量,则用平方误差最小化准则生成回归树;若为分类问题,用基尼指数最小化准则生成分类树。

对连续输入变量的处理:找到一个切分点将连续变量二值化,根据上述准则来选择切分点和最优切分变量

基尼指数的意义类似于熵,表示不确定性。

代码下载

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值