头歌--机器学习之决策树

这篇具有很好参考价值的文章主要介绍了头歌--机器学习之决策树。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

第1关:什么是决策树

第2关:信息熵与信息增益

第3关:使用ID3算法构建决策树

第4关:信息增益率

第5关:基尼系数

第6关:预剪枝与后剪枝

第7关:鸢尾花识别


第1关:什么是决策树

  • 1、下列说法正确的是?(AB)

    A、训练决策树的过程就是构建决策树的过程

    B、ID3算法是根据信息增益来构建决策树

    C、C4.5算法是根据基尼系数来构建决策树

    D、决策树模型的可理解性不高

  • 2、下列说法错误的是?(B)

    A、从树的根节点开始,根据特征的值一步一步走到叶子节点的过程是决策树做决策的过程
    B、决策树只能是一棵二叉树
    C、根节点所代表的特征是最优特征
    文章来源地址https://www.toymoban.com/news/detail-718149.html

第2关:信息熵与信息增益

import numpy as np


def calcInfoGain(feature, label, index):
    '''
    计算信息增益
    :param feature:测试用例中字典里的feature,类型为ndarray
    :param label:测试用例中字典里的label,类型为ndarray
    :param index:测试用例中字典里的index,即feature部分特征列的索引。该索引指的是feature中第几个特征,如index:0表示使用第一个特征来计算信息增益。
    :return:信息增益,类型float
    '''

    #*********** Begin ***********#
    def total_cal(label):
        label_set = set(label)
        result = 0
        for i in label_set:
            p=list(label).count(i)/len(label)
            result-=p * np.log2(p)
        return result
    aba=[]
    length=[]
    for value in set(feature[:,index]):
        # num=feature[:,index].count(value)
        sub_label = []
        for i in range(len(feature)):
            if feature[i][index] == value:
                sub_label.append(label[i])
        aba.append(total_cal(sub_label))
        length.append(len(sub_label)/len(label))
    res=total_cal(label)-length[0]*aba[0]-length[1]*aba[1]
    return res
    #*********** End *************#

第3关:使用ID3算法构建决策树

import numpy as np
class DecisionTree(object):
    def __init__(self):
        #决策树模型
        self.tree = {}
    def calcInfoGain(self, feature, label, index):
        '''
        计算信息增益
        :param feature:测试用例中字典里的feature,类型为ndarray
        :param label:测试用例中字典里的label,类型为ndarray
        :param index:测试用例中字典里的index,即feature部分特征列的索引。该索引指的是feature中第几个特征,如index:0表示使用第一个特征来计算信息增益。
        :return:信息增益,类型float
        '''
        # 计算熵
        def calcInfoEntropy(label):
            '''
            计算信息熵
            :param label:数据集中的标签,类型为ndarray
            :return:信息熵,类型float
            '''
            label_set = set(label)
            result = 0
            for l in label_set:
                count = 0
                for j in range(len(label)):
                    if label[j] == l:
                        count += 1
                # 计算标签在数据集中出现的概率
                p = count / len(label)
                # 计算熵
                result -= p * np.log2(p)
            return result
        # 计算条件熵
        def calcHDA(feature, label, index, value):
            '''
            计算信息熵
            :param feature:数据集中的特征,类型为ndarray
            :param label:数据集中的标签,类型为ndarray
            :param index:需要使用的特征列索引,类型为int
            :param value:index所表示的特征列中需要考察的特征值,类型为int
            :return:信息熵,类型float
            '''
            count = 0
            # sub_feature和sub_label表示根据特征列和特征值分割出的子数据集中的特征和标签
            sub_feature = []
            sub_label = []
            for i in range(len(feature)):
                if feature[i][index] == value:
                    count += 1
                    sub_feature.append(feature[i])
                    sub_label.append(label[i])
            pHA = count / len(feature)
            e = calcInfoEntropy(sub_label)
            return pHA * e
        base_e = calcInfoEntropy(label)
        f = np.array(feature)
        # 得到指定特征列的值的集合
        f_set = set(f[:, index])
        sum_HDA = 0
        # 计算条件熵
        for value in f_set:
            sum_HDA += calcHDA(feature, label, index, value)
        # 计算信息增益
        return base_e - sum_HDA
    # 获得信息增益最高的特征
    def getBestFeature(self, feature, label):
        max_infogain = 0
        best_feature = 0
        for i in range(len(feature[0])):
            infogain = self.calcInfoGain(feature, label, i)
            if infogain > max_infogain:
                max_infogain = infogain
                best_feature = i
        return best_feature
    def createTree(self, feature, label):
        # 样本里都是同一个label没必要继续分叉了
        if len(set(label)) == 1:
            return label[0]
        # 样本中只有一个特征或者所有样本的特征都一样的话就看哪个label的票数高
        if len(feature[0]) == 1 or len(np.unique(feature, axis=0)) == 1:
            vote = {}
            for l in label:
                if l in vote.keys():
                    vote[l] += 1
                else:
                    vote[l] = 1
            max_count = 0
            vote_label = None
            for k, v in vote.items():
                if v > max_count:
                    max_count = v
                    vote_label = k
            return vote_label
        # 根据信息增益拿到特征的索引
        best_feature = self.getBestFeature(feature, label)
        tree = {best_feature: {}}
        f = np.array(feature)
        # 拿到bestfeature的所有特征值
        f_set = set(f[:, best_feature])
        # 构建对应特征值的子样本集sub_feature, sub_label
        for v in f_set:
            sub_feature = []
            sub_label = []
            for i in range(len(feature)):
                if feature[i][best_feature] == v:
                    sub_feature.append(feature[i])
                    sub_label.append(label[i])
            # 递归构建决策树
            tree[best_feature][v] = self.createTree(sub_feature, sub_label)
        return tree
    def fit(self, feature, label):
        '''
        :param feature: 训练集数据,类型为ndarray
        :param label:训练集标签,类型为ndarray
        :return: None
        '''
        #************* Begin ************#
        self.tree = self.createTree(feature, label)
        #************* End **************#
    def predict(self, feature):
        '''
        :param feature:测试集数据,类型为ndarray
        :return:预测结果,如np.array([0, 1, 2, 2, 1, 0])
        '''
        #************* Begin ************#
        result = []
        def classify(tree, feature):
            if not isinstance(tree, dict):
                return tree
            t_index, t_value = list(tree.items())[0]
            f_value = feature[t_index]
            if isinstance(t_value, dict):
                classLabel = classify(tree[t_index][f_value], feature)
                return classLabel
            else:
                return t_value
        for f in feature:
            result.append(classify(self.tree, f))
        return np.array(result)


        #************* End **************#

第4关:信息增益率

import numpy as np

def calcInfoGain(feature, label, index):
    '''
    计算信息增益
    :param feature:测试用例中字典里的feature,类型为ndarray
    :param label:测试用例中字典里的label,类型为ndarray
    :param index:测试用例中字典里的index,即feature部分特征列的索引。该索引指的是feature中第几个特征,如index:0表示使用第一个特征来计算信息增益。
    :return:信息增益,类型float
    '''
    # 计算熵
    def calcInfoEntropy(label):
        '''
        计算信息熵
        :param label:数据集中的标签,类型为ndarray
        :return:信息熵,类型float
        '''

        label_set = set(label)
        result = 0
        for l in label_set:
            count = 0
            for j in range(len(label)):
                if label[j] == l:
                    count += 1
            # 计算标签在数据集中出现的概率
            p = count / len(label)
            # 计算熵
            result -= p * np.log2(p)
        return result

    # 计算条件熵
    def calcHDA(feature, label, index, value):
        '''
        计算信息熵
        :param feature:数据集中的特征,类型为ndarray
        :param label:数据集中的标签,类型为ndarray
        :param index:需要使用的特征列索引,类型为int
        :param value:index所表示的特征列中需要考察的特征值,类型为int
        :return:信息熵,类型float
        '''
        count = 0
        # sub_label表示根据特征列和特征值分割出的子数据集中的标签
        sub_label = []
        for i in range(len(feature)):
            if feature[i][index] == value:
                count += 1
                sub_label.append(label[i])
        pHA = count / len(feature)
        e = calcInfoEntropy(sub_label)
        return pHA * e

    base_e = calcInfoEntropy(label)
    f = np.array(feature)
    # 得到指定特征列的值的集合
    f_set = set(f[:, index])
    sum_HDA = 0
    # 计算条件熵
    for value in f_set:
        sum_HDA += calcHDA(feature, label, index, value)
    # 计算信息增益
    return base_e - sum_HDA


def calcInfoGainRatio(feature, label, index):
    '''
    计算信息增益率
    :param feature:测试用例中字典里的feature,类型为ndarray
    :param label:测试用例中字典里的label,类型为ndarray
    :param index:测试用例中字典里的index,即feature部分特征列的索引。该索引指的是feature中第几个特征,如index:0表示使用第一个特征来计算信息增益。
    :return:信息增益率,类型float
    '''

    #********* Begin *********#
    info_gain = calcInfoGain(feature, label, index)
    unique_value = list(set(feature[:, index]))
    IV = 0
    for value in unique_value:
        len_v = np.sum(feature[:, index] == value)
        IV -= (len_v/len(feature))*np.log2((len_v/len(feature)))
    return info_gain/IV
    #********* End *********#

第5关:基尼系数

import numpy as np

def calcGini(feature, label, index):
    '''
    计算基尼系数
    :param feature:测试用例中字典里的feature,类型为ndarray
    :param label:测试用例中字典里的label,类型为ndarray
    :param index:测试用例中字典里的index,即feature部分特征列的索引。该索引指的是feature中第几个特征,如index:0表示使用第一个特征来计算信息增益。
    :return:基尼系数,类型float
    '''

    #********* Begin *********#

    def _gini(label):
        unique_label = list(set(label))
        gini = 1
        for l in unique_label:
            p = np.sum(label == l)/len(label)
            gini -= p**2
        return gini
    unique_value = list(set(feature[:, index]))
    gini = 0
    for value in unique_value:
        len_v = np.sum(feature[:, index] == value)
        gini += (len_v/len(feature))*_gini(label[feature[:, index] == value])
    return gini
    #********* End *********#

第6关:预剪枝与后剪枝

import numpy as np
from copy import deepcopy
class DecisionTree(object):
    def __init__(self):
        #决策树模型
        self.tree = {}
    def calcInfoGain(self, feature, label, index):
        '''
        计算信息增益
        :param feature:测试用例中字典里的feature,类型为ndarray
        :param label:测试用例中字典里的label,类型为ndarray
        :param index:测试用例中字典里的index,即feature部分特征列的索引。该索引指的是feature中第几个特征,如index:0表示使用第一个特征来计算信息增益。
        :return:信息增益,类型float
        '''
        # 计算熵
        def calcInfoEntropy(feature, label):
            '''
            计算信息熵
            :param feature:数据集中的特征,类型为ndarray
            :param label:数据集中的标签,类型为ndarray
            :return:信息熵,类型float
            '''
            label_set = set(label)
            result = 0
            for l in label_set:
                count = 0
                for j in range(len(label)):
                    if label[j] == l:
                        count += 1
                # 计算标签在数据集中出现的概率
                p = count / len(label)
                # 计算熵
                result -= p * np.log2(p)
            return result
        # 计算条件熵
        def calcHDA(feature, label, index, value):
            '''
            计算信息熵
            :param feature:数据集中的特征,类型为ndarray
            :param label:数据集中的标签,类型为ndarray
            :param index:需要使用的特征列索引,类型为int
            :param value:index所表示的特征列中需要考察的特征值,类型为int
            :return:信息熵,类型float
            '''
            count = 0
            # sub_feature和sub_label表示根据特征列和特征值分割出的子数据集中的特征和标签
            sub_feature = []
            sub_label = []
            for i in range(len(feature)):
                if feature[i][index] == value:
                    count += 1
                    sub_feature.append(feature[i])
                    sub_label.append(label[i])
            pHA = count / len(feature)
            e = calcInfoEntropy(sub_feature, sub_label)
            return pHA * e
        base_e = calcInfoEntropy(feature, label)
        f = np.array(feature)
        # 得到指定特征列的值的集合
        f_set = set(f[:, index])
        sum_HDA = 0
        # 计算条件熵
        for value in f_set:
            sum_HDA += calcHDA(feature, label, index, value)
        # 计算信息增益
        return base_e - sum_HDA
    # 获得信息增益最高的特征
    def getBestFeature(self, feature, label):
        max_infogain = 0
        best_feature = 0
        for i in range(len(feature[0])):
            infogain = self.calcInfoGain(feature, label, i)
            if infogain > max_infogain:
                max_infogain = infogain
                best_feature = i
        return best_feature
    # 计算验证集准确率
    def calc_acc_val(self, the_tree, val_feature, val_label):
        result = []
        def classify(tree, feature):
            if not isinstance(tree, dict):
                return tree
            t_index, t_value = list(tree.items())[0]
            f_value = feature[t_index]
            if isinstance(t_value, dict):
                classLabel = classify(tree[t_index][f_value], feature)
                return classLabel
            else:
                return t_value
        for f in val_feature:
            result.append(classify(the_tree, f))
        result = np.array(result)
        return np.mean(result == val_label)
    def createTree(self, train_feature, train_label):
        # 样本里都是同一个label没必要继续分叉了
        if len(set(train_label)) == 1:
            return train_label[0]
        # 样本中只有一个特征或者所有样本的特征都一样的话就看哪个label的票数高
        if len(train_feature[0]) == 1 or len(np.unique(train_feature, axis=0)) == 1:
            vote = {}
            for l in train_label:
                if l in vote.keys():
                    vote[l] += 1
                else:
                    vote[l] = 1
            max_count = 0
            vote_label = None
            for k, v in vote.items():
                if v > max_count:
                    max_count = v
                    vote_label = k
            return vote_label
        # 根据信息增益拿到特征的索引
        best_feature = self.getBestFeature(train_feature, train_label)
        tree = {best_feature: {}}
        f = np.array(train_feature)
        # 拿到bestfeature的所有特征值
        f_set = set(f[:, best_feature])
        # 构建对应特征值的子样本集sub_feature, sub_label
        for v in f_set:
            sub_feature = []
            sub_label = []
            for i in range(len(train_feature)):
                if train_feature[i][best_feature] == v:
                    sub_feature.append(train_feature[i])
                    sub_label.append(train_label[i])
            # 递归构建决策树
            tree[best_feature][v] = self.createTree(sub_feature, sub_label)
        return tree
    # 后剪枝
    def post_cut(self, val_feature, val_label):
        # 拿到非叶子节点的数量
        def get_non_leaf_node_count(tree):
            non_leaf_node_path = []
            def dfs(tree, path, all_path):
                for k in tree.keys():
                    if isinstance(tree[k], dict):
                        path.append(k)
                        dfs(tree[k], path, all_path)
                        if len(path) > 0:
                            path.pop()
                    else:
                        all_path.append(path[:])
            dfs(tree, [], non_leaf_node_path)
            unique_non_leaf_node = []
            for path in non_leaf_node_path:
                isFind = False
                for p in unique_non_leaf_node:
                    if path == p:
                        isFind = True
                        break
                if not isFind:
                    unique_non_leaf_node.append(path)
            return len(unique_non_leaf_node)
        # 拿到树中深度最深的从根节点到非叶子节点的路径
        def get_the_most_deep_path(tree):
            non_leaf_node_path = []
            def dfs(tree, path, all_path):
                for k in tree.keys():
                    if isinstance(tree[k], dict):
                        path.append(k)
                        dfs(tree[k], path, all_path)
                        if len(path) > 0:
                            path.pop()
                    else:
                        all_path.append(path[:])
            dfs(tree, [], non_leaf_node_path)
            max_depth = 0
            result = None
            for path in non_leaf_node_path:
                if len(path) > max_depth:
                    max_depth = len(path)
                    result = path
            return result
        # 剪枝
        def set_vote_label(tree, path, label):
            for i in range(len(path)-1):
                tree = tree[path[i]]
            tree[path[len(path)-1]] = vote_label
        acc_before_cut = self.calc_acc_val(self.tree, val_feature, val_label)
        # 遍历所有非叶子节点
        for _ in range(get_non_leaf_node_count(self.tree)):
            path = get_the_most_deep_path(self.tree)
            # 备份树
            tree = deepcopy(self.tree)
            step = deepcopy(tree)
            # 跟着路径走
            for k in path:
                step = step[k]
            # 叶子节点中票数最多的标签
            vote_label = sorted(step.items(), key=lambda item: item[1], reverse=True)[0][0]
            # 在备份的树上剪枝
            set_vote_label(tree, path, vote_label)
            acc_after_cut = self.calc_acc_val(tree, val_feature, val_label)
            # 验证集准确率高于0.9才剪枝
            if acc_after_cut > acc_before_cut:
                set_vote_label(self.tree, path, vote_label)
                acc_before_cut = acc_after_cut
    def fit(self, train_feature, train_label, val_feature, val_label):
        '''
        :param train_feature:训练集数据,类型为ndarray
        :param train_label:训练集标签,类型为ndarray
        :param val_feature:验证集数据,类型为ndarray
        :param val_label:验证集标签,类型为ndarray
        :return: None
        '''
        #************* Begin ************#
        self.tree = self.createTree(train_feature, train_label)
        # 后剪枝
        self.post_cut(val_feature, val_label)


        #************* End **************#
    def predict(self, feature):
        '''
        :param feature:测试集数据,类型为ndarray
        :return:预测结果,如np.array([0, 1, 2, 2, 1, 0])
        '''
        #************* Begin ************#

        result = []
 
        # 单个样本分类
        def classify(tree, feature):
            if not isinstance(tree, dict):
                return tree
            t_index, t_value = list(tree.items())[0]
            f_value = feature[t_index]
            if isinstance(t_value, dict):
                classLabel = classify(tree[t_index][f_value], feature)
                return classLabel
            else:
                return t_value
 
        for f in feature:
            result.append(classify(self.tree, f))
 
        return np.array(result)
        #************* End **************#

第7关:鸢尾花识别

#********* Begin *********#

import pandas as pd
from sklearn.tree import DecisionTreeClassifier
 
train_df = pd.read_csv('./step7/train_data.csv').as_matrix()
train_label = pd.read_csv('./step7/train_label.csv').as_matrix()
test_df = pd.read_csv('./step7/test_data.csv').as_matrix()
 
dt = DecisionTreeClassifier()
dt.fit(train_df, train_label)
result = dt.predict(test_df)
 
result = pd.DataFrame({'target':result})
result.to_csv('./step7/predict.csv', index=False)
#********* End *********#

到了这里,关于头歌--机器学习之决策树的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 机器学习之——CART决策树算法

    目录 一、CART决策树算法简介 二、基尼系数 三、决策树的生成 CART(Classification And Regression Trees 分类回归树)算法是一种树构建算法,既可以用于分类任务,又可以用于回归。相比于 ID3 和 C4.5 只能用于 离散型数据 且只能用于分类任务,CART 算法的适用面要广得多,既可用于

    2024年04月13日
    浏览(36)
  • 机器学习之决策树CART算法

    接上期: CART算法是给定输入随机变量X条件下输出随机变量Y的条件概率分布的学习方法。CART假设决策树是二叉树,内部节点取值为“是”或“否”。这样的决策树等价于递归地二分每个特征,将特征空间划分为有限个单元,并在这些单元上确定预测的概率分布即输入给定的

    2024年02月02日
    浏览(32)
  • 机器学习之分类决策树与回归决策树—基于python实现

          大家好,我是带我去滑雪!       本期为大家介绍决策树算法,它一种基学习器,广泛应用于集成学习,用于大幅度提高模型的预测准确率。决策树在分区域时,会考虑特征向量对响应变量的影响,且每次仅使用一个分裂变量,这使得决策树很容易应用于高维空间,且

    2024年02月03日
    浏览(32)
  • 【Python机器学习】决策树——树的特征重要性

    利用一些有用的属性来总结树的工作原理,其中最常用的事特征重要性,它为每个特征树的决策的重要性进行排序。对于每个特征来说,它都是介于0到1之间的数字,其中0代表“根本没有用到”,1代表“完美预测目标值”。特征重要性的求和为1。 将特征重要性进行可视化:

    2024年02月03日
    浏览(42)
  • 决策树的原理、方法以及python实现——机器学习笔记

    * * * * * *  The Machine Learning Noting Series  * * * * * * 决 策树(Decision Tree)是机器学习的核心算法之一,在较小训练样本或有限计算资源下仍有较好表现,它包括分类树和回归树,是目前应用最广泛的分类预测和回归预测方法。 0 引言 1 决策树的概念     分类树     回归树 2  

    2024年02月04日
    浏览(40)
  • 机器学习---决策树的划分依据(熵、信息增益、信息增益率、基尼值和基尼指数)

    1. 熵 物理学上,熵 Entropy 是“混乱”程度的量度。 系统越有序,熵值越低;系统越混乱或者分散,熵值越⾼。 1948年⾹农提出了信息熵(Entropy)的概念。        从信息的完整性上进⾏的描述:当系统的有序状态⼀致时,数据越集中的地⽅熵值越⼩,数据 越分散的地⽅熵值

    2024年02月10日
    浏览(35)
  • 基于应用值迭代的马尔可夫决策过程(MDP)的策略的机器人研究(Matlab代码实现)

     💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码实现 MDP(

    2024年02月15日
    浏览(33)
  • 学习 TensorFlow:构建和训练机器学习模型的利器

    TensorFlow 是一种强大的开源机器学习框架,被广泛应用于构建和训练各种类型的神经网络模型。本文将介绍 TensorFlow 的基本概念、特点和学习步骤,同时提供一个项目案例和练习题,帮助读者快速入门和掌握 TensorFlow。 强大的计算图:TensorFlow 使用计算图来表示计算任务,将复

    2024年02月09日
    浏览(26)
  • 机器学习任务中使用计算图构建和训练模型的流程

    The goal is to encourage the project team to think more long-term and not judge success solely based on tactical results. This requires a shift in mindset to prioritize strategic thinking and understanding the bigger picture. It involves reevaluating the current perspective and approach to ensure that decisions and actions align with long-term goals and obje

    2024年02月10日
    浏览(33)
  • 机器人技能学习-构建自己的数据集并进行训练

    若想训练自己的场景,数据集的重要性不做过多赘述,下面就基于 robomimic 和 robosuite 构建自己的数据集进行讲解,同时,也会附上 train 和 run 的流程,这样,就形成了闭环。 采集数据可使用脚本 collect_human_demonstrations.py 完成,在采集过程中,需要自己定义 env 的相关信息,在实际

    2024年01月16日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包