(c#实现)决策树算法原理和案例

一、引言

        决策树(Decision Tree)是一种常用的监督学习算法,广泛应用于分类和回归任务。它的直观性和可解释性使其成为机器学习和数据挖掘领域的重要工具。本文将详细介绍决策树的原理,并通过一个实际案例展示如何使用C#实现决策树算法。

二、决策树的基本原理

1. 决策树的结构

决策树由节点(Node)和边(Edge)组成,其中节点分为三类:

  • 根节点(Root Node):树的起点,包含整个数据集。
  • 内部节点(Internal Node):决策点,根据特定特征进行分裂。
  • 叶节点(Leaf Node):树的终点,表示分类结果或回归值。
2. 决策树的构建

决策树的构建过程主要包括以下步骤:

  1. 选择最佳分裂特征:根据某种分裂准则(如信息增益、基尼指数等)选择最佳特征进行分裂。
  2. 分裂节点:根据选定的特征将数据集分成若干子集。
  3. 递归构建子树:对每个子集重复上述过程,直至满足停止条件(如节点纯度足够高、树的深度达到预设值等)。
3. 分裂准则

常用的分裂准则包括:

  • 信息增益(Information Gain):衡量特征对分类结果的不确定性的减少程度,常用于ID3算法。
  • 信息增益率(Information Gain Ratio):修正了信息增益偏向于选择多值特征的问题,常用于C4.5算法。
  • 基尼指数(Gini Index):衡量数据集的不纯度,常用于CART算法。

三、决策树的实现案例

1. 案例介绍

我们将使用C#实现一个简单的决策树分类器,来解决“玩游戏”数据集的分类问题。数据集包含多个特征,如天气、温度、湿度、风速等,目标是预测在给定条件下是否适合玩游戏。

2. 数据集

示例数据集如下:

在代码中我们可以这么实现:

using System;
using System.Collections.Generic;

class DecisionTree
{
    public string Attribute { get; set; }
    public Dictionary<string, DecisionTree> Children { get; set; } = new Dictionary<string, DecisionTree>();
    public string Label { get; set; }

    // 计算信息增益
    private static double CalculateEntropy(List<Dictionary<string, string>> data, string attribute)
    {
        Dictionary<string, int> labelCounts = new Dictionary<string, int>();
        foreach (var row in data)
        {
            if (!labelCounts.ContainsKey(row[attribute]))
                labelCounts[row[attribute]] = 0;
            labelCounts[row[attribute]]++;
        }

        double entropy = 0.0;
        foreach (var count in labelCounts.Values)
        {
            double probability = (double)count / data.Count;
            entropy -= probability * Math.Log2(probability);
        }

        return entropy;
    }

    // 选择最佳分裂特征
    private static string ChooseBestAttribute(List<Dictionary<string, string>> data, List<string> attributes)
    {
        double baseEntropy = CalculateEntropy(data, "适合玩游戏");
        double bestInfoGain = 0.0;
        string bestAttribute = null;

        foreach (var attribute in attributes)
        {
            double attributeEntropy = 0.0;
            Dictionary<string, List<Dictionary<string, string>>> attributeValues = new Dictionary<string, List<Dictionary<string, string>>>();

            foreach (var row in data)
            {
                if (!attributeValues.ContainsKey(row[attribute]))
                    attributeValues[row[attribute]] = new List<Dictionary<string, string>>();
                attributeValues[row[attribute]].Add(row);
            }

            foreach (var subset in attributeValues.Values)
            {
                double subsetProbability = (double)subset.Count / data.Count;
                attributeEntropy += subsetProbability * CalculateEntropy(subset, "适合玩游戏");
            }

            double infoGain = baseEntropy - attributeEntropy;
            if (infoGain > bestInfoGain)
            {
                bestInfoGain = infoGain;
                bestAttribute = attribute;
            }
        }

        return bestAttribute;
    }

    // 构建决策树
    public static DecisionTree BuildTree(List<Dictionary<string, string>> data, List<string> attributes)
    {
        DecisionTree tree = new DecisionTree();

        Dictionary<string, int> labelCounts = new Dictionary<string, int>();
        foreach (var row in data)
        {
            if (!labelCounts.ContainsKey(row["适合玩游戏"]))
                labelCounts[row["适合玩游戏"]] = 0;
            labelCounts[row["适合玩游戏"]]++;
        }

        if (labelCounts.Count == 1)
        {
            tree.Label = labelCounts.Keys.GetEnumerator().Current;
            return tree;
        }

        if (attributes.Count == 0)
        {
            tree.Label = GetMajorityLabel(labelCounts);
            return tree;
        }

        string bestAttribute = ChooseBestAttribute(data, attributes);
        tree.Attribute = bestAttribute;

        Dictionary<string, List<Dictionary<string, string>>> attributeValues = new Dictionary<string, List<Dictionary<string, string>>>();
        foreach (var row in data)
        {
            if (!attributeValues.ContainsKey(row[bestAttribute]))
                attributeValues[row[bestAttribute]] = new List<Dictionary<string, string>>();
            attributeValues[row[bestAttribute]].Add(row);
        }

        List<string> remainingAttributes = new List<string>(attributes);
        remainingAttributes.Remove(bestAttribute);

        foreach (var attributeValue in attributeValues.Keys)
        {
            tree.Children[attributeValue] = BuildTree(attributeValues[attributeValue], remainingAttributes);
        }

        return tree;
    }

    // 获取多数标签
    private static string GetMajorityLabel(Dictionary<string, int> labelCounts)
    {
        string majorityLabel = null;
        int maxCount = 0;

        foreach (var label in labelCounts.Keys)
        {
            if (labelCounts[label] > maxCount)
            {
                maxCount = labelCounts[label];
                majorityLabel = label;
            }
        }

        return majorityLabel;
    }

    // 打印决策树
    public void PrintTree(string indent = "")
    {
        if (Label != null)
        {
            Console.WriteLine(indent + "Label: " + Label);
        }
        else
        {
            Console.WriteLine(indent + "Attribute: " + Attribute);
            foreach (var child in Children.Keys)
            {
                Console.WriteLine(indent + "  " + child + ":");
                Children[child].PrintTree(indent + "    ");
            }
        }
    }
}

class Program
{
    static void Main()
    {
        // 示例数据集
        List<Dictionary<string, string>> data = new List<Dictionary<string, string>>
        {
            new Dictionary<string, string> { { "天气", "晴朗" }, { "温度", "高" }, { "湿度", "高" }, { "风速", "弱" }, { "适合玩游戏", "否" } },
            new Dictionary<string, string> { { "天气", "晴朗" }, { "温度", "高" }, { "湿度", "高" }, { "风速", "强" }, { "适合玩游戏", "否" } },
            new Dictionary<string, string> { { "天气", "阴天" }, { "温度", "高" }, { "湿度", "高" }, { "风速", "弱" }, { "适合玩游戏", "是" } },
            new Dictionary<string, string> { { "天气", "雨天" }, { "温度", "适中" }, { "湿度", "高" }, { "风速", "弱" }, { "适合玩游戏", "是" } },
            new Dictionary<string, string> { { "天气", "雨天" }, { "温度", "低" }, { "湿度", "正常" }, { "风速", "弱" }, { "适合玩游戏", "是" } },
            new Dictionary<string, string> { { "天气", "雨天" }, { "温度", "低" }, { "湿度", "正常" }, { "风速", "强" }, { "适合玩游戏", "否" } },
            new Dictionary<string, string> { { "天气", "阴天" }, { "温度", "低" }, { "湿度", "正常" }, { "风速", "强" }, { "适合玩游戏", "是" } },
            new Dictionary<string, string> { { "天气", "晴朗" }, { "温度", "适中" }, { "湿度", "高" }, { "风速", "弱" }, { "适合玩游戏", "否" } },
            new Dictionary<string, string> { { "天气", "晴朗" }, { "温度", "低" }, { "湿度", "正常" }, { "风速", "弱" }, { "适合玩游戏", "是" } },
            new Dictionary<string, string> { { "天气", "雨天" }, { "温度", "适中" }, { "湿度", "正常" }, { "风速", "弱" }, { "适合玩游戏", "是" } },
            new Dictionary<string, string> { { "天气", "晴朗" }, { "温度", "适中" }, { "湿度", "正常" }, { "风速", "强" }, { "适合玩游戏", "是" } },
            new Dictionary<string, string> { { "天气", "阴天" }, { "温度", "适中" }, { "湿度", "高" }, { "风速", "强" }, { "适合玩游戏", "是" } },
            new Dictionary<string, string> { { "天气", "阴天" }, { "温度", "高" }, { "湿度", "正常" }, { "风速", "弱" }, { "适合玩游戏", "是" } },
            new Dictionary<string, string> { { "天气", "雨天" }, { "温度", "适中" }, { "湿度", "高" }, { "风速", "强" }, { "适合玩游戏", "否" } },
        };

        List<string> attributes = new List<string> { "天气", "温度", "湿度", "风速" };

        // 构建决策树
        DecisionTree tree = DecisionTree.BuildTree(data, attributes);

        // 打印决策树
        tree.PrintTree();
    }
}

        决策树算法的优势在于其直观性和易解释性,但也存在过拟合等问题,在实际应用中需要结合剪枝等技术进行优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/792521.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MindSpore学习打卡】应用实践-LLM原理和实践-基于MindSpore实现BERT对话情绪识别

在当今的自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;情绪识别是一个非常重要的应用场景。无论是在智能客服、社交媒体分析&#xff0c;还是在情感计算领域&#xff0c;准确地识别用户的情绪都能够极大地提升用户体验和系统的智能化水平。BERT&#xff08;Bidirec…

C++类和对象学习笔记

1.类的定义 1.1类定义的格式 class是定义类的关键字&#xff0c;Date为类的名字&#xff0c;{ }中为类的主体&#xff0c;注意定义类结束时后面的分号不能省略。类中的内容称为类的成员&#xff1b;类中的变量称为类的属性或成员变量&#xff1b;类中的函数称为类的方法或者成…

jdk1.8安装教程及环境变量配置(含jdk8,11,13安装文件)

目录 友情提醒第一章、JVM、JRE、JDK介绍第二章、下载和安装JDK2.1&#xff09;百度网盘直接下载免安装2.2&#xff09;官网下载安装JDK&#xff08;需要收费&#xff09; 第三章、环境变量配置3.1&#xff09;windows环境变量配置3.2&#xff09;验证环境变量是否配置成功 友情…

类和对象——【运算符重载】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件iostream的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …

PDA:Prompt-based Distribution Alignment for Unsupervised Domain Adaptation

文章汇总 式中&#xff0c; y s y^s ys表示源域数据的one-hot ground-truth&#xff0c; K K K为类数&#xff0c; w i w_i wi​和 z ~ s \tilde{z}_s z~s​分别表示源域经过提示调优的最终文本表示和最终图像表示的第 i i i类。 同理&#xff0c;为了进一步利用目标领域的数据…

ARMV8安全特性:Pointer Authentication

文章目录 前言一、Introduction二、Problem Definition三、Pointer Authentication3.1 Instructions3.2 Cryptography3.3 Key Management 四、Sample Use Cases4.1 Software Stack Protection4.2 Control Flow Integrity (CFI)4.3 Binding Pointers to Addresses 五、Security …

B2B领域的客户裂变策略:打造行业内的共赢生态

在日益竞争激烈的B2B市场中&#xff0c;客户裂变作为一种高效的增长策略&#xff0c;不仅能够帮助企业快速扩大客户基础&#xff0c;还能促进行业内资源共享与合作&#xff0c;共同构建一个健康、可持续的共赢生态。本文将探讨B2B领域实施客户裂变策略的关键要素&#xff0c;以…

【数据结构】排序——快速排序

前言 本篇博客我们继续介绍一种排序——快速排序&#xff0c;让我们看看快速排序是怎么实现的 &#x1f493; 个人主页&#xff1a;小张同学zkf ⏩ 文章专栏&#xff1a;数据结构 若有问题 评论区见&#x1f4dd; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 ​ 目录 …

“学习Pandas中时间序列的基本操作“

目录 # 开篇 1. 创建和操作时间序列对象 2. 时间序列数据的读取和存储 3. 时间序列数据的索引和切片 4. 时间序列数据的操作和转换 5. 时间序列数据的可视化 6. 处理时间序列中的缺失值 7. 时间序列数据的聚合和分组 8. 时间序列的时间区间和偏移量操作 示例代码&…

重要文件放u盘还是硬盘?硬盘和u盘哪个适合长期存储

在数字时代&#xff0c;我们每天都会处理大量的文件。其中&#xff0c;不乏一些对我们而言至关重要的文件&#xff0c;如家庭照片、工作文档、财务记录等。面对这些重要文件的存储问题&#xff0c;我们通常会面临&#xff1a;“重要文件放U盘还是硬盘”、“硬盘和U盘哪个适合长…

qt creator中右边的的类和对象如何显示出来

qt creator中右边的的类和对象如何显示出来&#xff1f; 解决方法&#xff1a; 鼠标右键&#xff0c;重置为默认布局。

特征值究竟体现了矩阵的什么特征?

特征值究竟体现了矩阵的什么特征&#xff1f; 简单来说就是x经过矩阵A映射后和自己平行 希尔伯特第一次提出eigenvalue,这里的eigen就是自己的。所以eigenvalue也称作本征值 特征值和特征向量刻画了矩阵变换空间的特征 对平面上的任意向量可以如法炮制&#xff0c;把他在特征…

【Linux】任务管理

这个任务管理&#xff08;job control&#xff09;是用在bash环境下的&#xff0c;也就是说&#xff1a;【当我们登录系统获取bashshell之后&#xff0c;在单一终端下同时执行多个任务的操作管理】。 举例来说&#xff0c;我们在登录bash后&#xff0c;可以一边复制文件、一边查…

Linux--线程ID封装管理原生线程

目录 1.线程的tid&#xff08;本质是线程属性集合的起始虚拟地址&#xff09; 1.1pthread库中线程的tid是什么&#xff1f; 1.2理解库 1.3phtread库中做了什么&#xff1f; 1.4线程的tid&#xff0c;和内核中的lwp 1.5线程的局部存储 2.封装管理原生线程库 1.线程的tid…

8.9分王者“水刊”!1区IEEE-Trans,国人主编坐镇!发文量2倍增长,扩刊趋势明显!

关注GZH【欧亚科睿学术】&#xff0c;第一时间了解最新期刊动态&#xff01; 本期&#xff0c;小编给大家推荐的是一本IEEE旗下王者“水刊”。该期刊目前处于扩刊状态&#xff0c;接收跨学科领域&#xff0c;领域认可度高&#xff0c;还可选择非OA模式无需版面费&#xff0c;是…

css看见彩虹,吃定彩虹

css彩虹 .f111 {width: 200px;height: 200px;border-radius: 50%;box-shadow: 0 0 0 5px inset red, 0 0 0 10px inset orange, 0 0 0 15px inset yellow, 0 0 0 20px inset lime, 0 0 0 25px inset aqua, 0 0 0 30px inset blue, 0 0 0 35px inset magenta;clip-path: polygo…

力扣爆刷第163天之TOP100五连刷81-85(回文链表、路径和、最长重复子数组)

力扣爆刷第163天之TOP100五连刷81-85&#xff08;回文链表、路径和、最长重复子数组&#xff09; 文章目录 力扣爆刷第163天之TOP100五连刷81-85&#xff08;回文链表、路径和、最长重复子数组&#xff09;一、234. 回文链表二、112. 路径总和三、169. 多数元素四、662. 二叉树…

盲人出行好帮手:蝙蝠避障让走路变简单

在一片无光的世界里&#xff0c;每一步都承载着探索与勇气。我是众多盲人中的一员&#xff0c;每天的出行不仅是从&#xff21;点到&#xff22;点的物理移动&#xff0c;更是一场心灵的征程。我的世界&#xff0c;虽然被剥夺了视觉的馈赠&#xff0c;却因科技的力量而变得宽广…

保护企业数据资产的策略与实践:数据安全治理技术之实战篇!

在上篇文章中&#xff0c;我们深入讨论了数据安全治理技术的前期准备工作&#xff0c;包括从建立数据安全运维体系、敏感数据识别、数据的分类与分级到身份认等方面的详细规划和设计。这些准备工作是实现数据安全治理的基础&#xff0c;它们为企业建立起一套系统化、标准化的数…

2.电容(常见元器件及电路基础知识)

一.电容种类 1.固态电容 这种一般价格贵一些&#xff0c;ESR,ESL比较低,之前项目400W电源用的就是这个&#xff0c;温升能够很好的控制 2.铝电解电容 这种一般很便宜&#xff0c;ESR,ESL相对大一些&#xff0c;一般发热量比较大&#xff0c;烫手。 这种一般比上一个贵一点&am…