决策树及其python实现(机器学习)

1.决策树

1.1介绍

什么是决策树?

 分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点有向边组成。结点有两种类型:内部结点叶节点。内部结点表示一个特征或属性,叶节点表示一个类

1.2 决策树学习的三个步骤

特征选择
特征选择决定了使用哪些特征来做判断。在训练数据集中,每个样本的属性可能有很多个,不同属性的作用有大有小。因而特征选择的作用就是筛选出跟分类结果相关性较高的特征,也就是分类能力较强的特征。
在特征选择中通常使用的准则是:信息增益。

决策树生成
选择好特征后,就从根节点触发,对节点计算所有特征的信息增益,选择信息增益最大的特征作为节点特征,根据该特征的不同取值建立子节点;对每个子节点使用相同的方式生成新的子节点,直到信息增益很小或者没有特征可以选择为止。

决策树剪枝
剪枝的主要目的是对抗「过拟合」,通过主动去掉部分分支来降低过拟合的风险。

      1.3 三种典型的决策树

ID3 算法

ID3 是最早提出的决策树算法,他就是利用信息增益来选择特征的。

C4.5 算法

他是 ID3 的改进版,他不是直接使用信息增益,而是引入“信息增益比”指标作为特征的选择依据。

CART(Classification and Regression Tree)

这种算法即可以用于分类,也可以用于回归问题。CART 算法使用了基尼系数取代了信息熵模型。

1.3.1 ID3算法

1.信息熵

信息熵 ”是 度量样本集合纯度最常用的一种指标 ,假定当前样本集合 D 中第 k 类样本所占的比例为 p k ( K =1, 2, ..., | y |)  , D 的信息熵为
Ent\left ( D \right )=-\sum_{K=1}^{\left | y \right |}pk\log _{2}^{pk}

Ent(D)的值越小,则D的纯度越高

计算信息熵时约定:若p = 0,则plog2p=0

Ent(D)的最小值为0,最大值为log2|y|

2.信息增益

离散属性aV个可能的取值{a1, a2, ..., aV},用a来进行划分,则会产生V个分支结点,其中第v个分支结点包含了D中所有在属性a上取值av的样本,记为Dv。则可计算出用属性a对样本集D进行划分所获得的“信息增益”:

Gain\left ( D,a \right )=Ent\left ( D \right )-\frac{\left |D ^v \right |}{^{^{D}}}Ent\left ( D^v\right )

1.3.2C4.5算法

1.增益率

信息增益的缺点在于对取值数目较多的属性有所偏好

C4.5决策树算法不直接使用信息增益,而是使用增益率(gain ratio)来选择最优划分属性,用公式表述为:

Gain-ration(D,a)=\frac{Gain(D,a)}{IV(a)}

其中,G a i n ( D , a ) 同上文中的信息增益,
IV(a)=\sum_{v=1}^{V}\frac{\left | D^v \right |}{\left | D \right |}\log _{2}^{\frac{}{}}\frac{\left | D^v \right |}{\left | D \right |}

被称为特征a的固有值,属性a的取值越多 IV(a)的值越大,Gain_ration越小

1.3.3 CART

CART决策树与前面两个都不同,它采用基尼指数划分属性,计算公式如下

Ginin(D,a)=\sum_{k=1}^{\left | y \right |}p_{k}(1-p_{k})=1-\sum_{k=1}^{\left | y \right |}p_{k}^{2}

∣y∣表示类别个数

当做二分类时,公式可以简化为:

Ginin(D)=2p(1-p)

2.python实现

数据集使用西瓜数据集2.0

数据集链接

链接:https://pan.baidu.com/s/1trGDz9M1BT6reFzfXeEzkQ 
提取码:6666

ID3决策树基础代码实现
根据决策树算法,可知I3D决策树的算法流程如下:

先根据最大信息增益选取一个特征作为根节点
以根节点特征的取值作为分支递归生成节点,在递归中注意:
每次取特征值时需要删除之前取过的数据
当当前样本只有一类时,返回该类别作叶子结点,即分类结果
当当前所有样本的特征值都一样时,选样本最多的类作为叶子结点
使用测试特征测试决策树预测能力

import pandas as pd
import numpy as np

#计算信息熵
def cal_information_entropy(data):
    data_label = data.iloc[:,-1]
    label_class =data_label.value_counts() #总共有多少类
    Ent = 0
    for k in label_class.keys():
        p_k = label_class[k]/len(data_label)
        Ent += -p_k*np.log2(p_k)
    return Ent

#计算给定数据属性a的信息增益
def cal_information_gain(data, a):
    Ent = cal_information_entropy(data)
    feature_class = data[a].value_counts() #特征有多少种可能
    gain = 0
    for v in feature_class.keys():
        weight = feature_class[v]/data.shape[0]
        Ent_v = cal_information_entropy(data.loc[data[a] == v])
        gain += weight*Ent_v
    return Ent - gain

#获取标签最多的那一类
def get_most_label(data):
    data_label = data.iloc[:,-1]
    label_sort = data_label.value_counts(sort=True)
    return label_sort.keys()[0]

#挑选最优特征,即信息增益最大的特征
def get_best_feature(data):
    features = data.columns[:-1]
    res = {}
    for a in features:
        temp = cal_information_gain(data, a)
        res[a] = temp
    res = sorted(res.items(),key=lambda x:x[1],reverse=True)
    return res[0][0]

##将数据转化为(属性值:数据)的元组形式返回,并删除之前的特征列
def drop_exist_feature(data, best_feature):
    attr = pd.unique(data[best_feature])
    new_data = [(nd, data[data[best_feature] == nd]) for nd in attr]
    new_data = [(n[0], n[1].drop([best_feature], axis=1)) for n in new_data]
    return new_data

#创建决策树
def create_tree(data):
    data_label = data.iloc[:,-1]
    if len(data_label.value_counts()) == 1: #只有一类
        return data_label.values[0]
    if all(len(data[i].value_counts()) == 1 for i in data.iloc[:,:-1].columns): #所有数据的特征值一样,选样本最多的类作为分类结果
        return get_most_label(data)
    best_feature = get_best_feature(data) #根据信息增益得到的最优划分特征
    Tree = {best_feature:{}} #用字典形式存储决策树
    exist_vals = pd.unique(data[best_feature]) #当前数据下最佳特征的取值
    if len(exist_vals) != len(column_count[best_feature]): #如果特征的取值相比于原来的少了
        no_exist_attr = set(column_count[best_feature]) - set(exist_vals) #少的那些特征
        for no_feat in no_exist_attr:
            Tree[best_feature][no_feat] = get_most_label(data) #缺失的特征分类为当前类别最多的

    for item in drop_exist_feature(data,best_feature): #根据特征值的不同递归创建决策树
        Tree[best_feature][item[0]] = create_tree(item[1])
    return Tree

#{'纹理': {'清晰': {'根蒂': {'蜷缩': 1, '稍蜷': {'色泽': {'青绿': 1, '乌黑': {'触感': {'硬滑': 1, '软粘': 0}}}}, '硬挺': 0}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}

def predict(Tree, test_data):
    first_feature = next(iter(Tree))
    second_dict = Tree[first_feature]
    input_first = test_data.get(first_feature)
    if input_first is None:
        return None  # 返回一个适当的默认值,表示无法进行分类
    input_value = second_dict.get(input_first)
    if input_value is None:
        return None  # 返回一个适当的默认值,表示无法进行分类
    if isinstance(input_value, dict):  #判断分支还是不是字典
        class_label = predict(input_value, test_data)
    else:
        class_label = input_value
    return class_label

if __name__ == '__main__':
    #读取数据
    data = pd.read_csv(r'C:\Users\zhoutao\Desktop\data_word.csv')

    #统计每个特征的取值情况作为全局变量
    column_count = dict([(ds, list(pd.unique(data[ds]))) for ds in data.iloc[:, :-1].columns])

    #创建决策树
    dicision_Tree = create_tree(data)
    print(dicision_Tree)
 #测试数据
test_data_1 = {'色泽': '青绿', '根蒂': '蜷缩', '敲声': '浊响', '纹理': '稍糊', '脐部': '凹陷', '触感': '硬滑'}
test_data_2 = {'色泽': '乌黑', '根蒂': '稍蜷', '敲声': '浊响', '纹理': '清晰', '脐部': '凹陷', '触感': '硬滑'}

result = predict(dicision_Tree, test_data_2)
if result is None:
    print('无法分类')
else:
    print('分类结果为' + '好瓜' if result == 1 else '坏瓜')

c4.5决策树基础代码实现

基本上和ID3一样只是特征选取部分需要修改

原先的代码(将以下的代码修改即可)

#获取标签最多的那一类
def get_most_label(data):
    data_label = data.iloc[:,-1]
    label_sort = data_label.value_counts(sort=True)
    return label_sort.keys()[0]

#挑选最优特征,即信息增益最大的特征
def get_best_feature(data):
    features = data.columns[:-1]
    res = {}
    for a in features:
        temp = cal_information_gain(data, a)
        res[a] = temp
    res = sorted(res.items(),key=lambda x:x[1],reverse=True)
    return res[0][0]

​

这是修改好的代码

def cal_gain_ratio(data , a):
    #先计算固有值intrinsic_value
    IV_a = 0
    feature_class = data[a].value_counts()  # 特征有多少种可能
    for v in feature_class.keys():
        weight = feature_class[v]/data.shape[0]
        IV_a += -weight*np.log2(weight)
    gain_ration = cal_information_gain(data,a)/IV_a
    return gain_ration

#获取标签最多的那一类
def get_most_label(data):
    data_label = data.iloc[:,-1]
    label_sort = data_label.value_counts(sort=True)
    return label_sort.keys()[0]

#挑选最优特征,即在信息增益大于平均水平的特征中选取增益率最高的特征
def get_best_feature(data):
    features = data.columns[:-1]
    res = {}
    for a in features:
        temp = cal_information_gain(data, a)
        gain_ration = cal_gain_ratio(data,a)
        res[a] = (temp,gain_ration)
    res = sorted(res.items(),key=lambda x:x[1][0],reverse=True) #按信息增益排名
    res_avg = sum([x[1][0] for x in res])/len(res) #信息增益平均水平
    good_res = [x for x in res if x[1][0] >= res_avg] #选取信息增益高于平均水平的特征
    result =sorted(good_res,key=lambda x:x[1][1],reverse=True) #将信息增益高的特征按照增益率进行排名
    return result[0][0] #返回高信息增益中增益率最大的特征

3.小结

增益率会对可取值数目较小的特征有偏好,为了避免这个问题,C4.5并不是直接使用增益率的大小进行划分特征,而是先从候选划分特征中找出信息增益高于平均水平的属性,再从中选择增益率最高的那个特征

参考文献

周志华《机器学习》

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的机器学习决策树的实例,使用Python实现: 首先,我们需要导入需要的库: ```python import pandas as pd from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn import metrics ``` 然后,我们可以使用Pandas库来读取我们的训练数据。这里我们使用一个名为“iris”的数据集,它包含了150个鸢尾花的样本。每个样本包含了四个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度)以及一个类别标签(鸢尾花的种类)。 ```python # 读取数据集 iris = pd.read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv') ``` 接着,我们需要将数据集分为训练集和测试集。在这个例子中,我们将80%的样本用于训练,20%的样本用于测试。 ```python # 将数据集分为训练集和测试集 X = iris.iloc[:, :-1] y = iris.iloc[:, -1] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) ``` 现在我们可以使用scikit-learn库中的DecisionTreeClassifier类来创建决策树型。在这个例子中,我们使用的是默认的参数。 ```python # 创建决策树型 dtc = DecisionTreeClassifier() dtc.fit(X_train, y_train) ``` 我们可以使用测试集来评估我们的型的性能。在这个例子中,我们使用了准确率来评估型的性能。 ```python # 使用测试集评估型的性能 y_pred = dtc.predict(X_test) print("准确率:", metrics.accuracy_score(y_test, y_pred)) ``` 最后,我们可以使用训练好的型来进行预测。在这个例子中,我们使用了一个包含三个样本的测试集来进行预测。 ```python # 使用训练好的型进行预测 test_data = [[5.1, 3.5, 1.4, 0.2], [6.2, 3.4, 5.4, 2.3], [4.9, 2.4, 3.3, 1.0]] predictions = dtc.predict(test_data) print("预测结果:", predictions) ``` 这就是一个简单的机器学习决策树的实例,使用Python实现

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值