【机器学习】ID3、C4.5、CART 算法

news2024/11/21 2:28:52

目录

常见的决策树算法

1. ID3

2. C4.5

3. CART

决策树的优缺点

优点:

缺点:

决策树的优化

常见的决策树算法

1. ID3

ID3(Iterative Dichotomiser 3)算法使用信息增益作为特征选择的标准。它是一种贪心算法,信息增益表示按某特征划分数据集前后信息熵的变化量,变化量越大,表示使用该特征划分的效果越好。但ID3偏向于选择取值较多的特征,可能导致过拟合。

以下是ID3算法的实现步骤:

1. 计算数据集的熵:熵是度量数据集无序程度的指标。
2. 计算每个属性的信息增益:信息增益是数据集的熵减去按照该属性分割后的条件熵。
3. 选择信息增益最大的属性:作为决策节点。
4. 分割数据集:根据选定的属性和它的值,将数据集分割成若干子集。
5. 递归构建决策树:对每个子集重复步骤1-4,直到所有数据都属于同一类别,或者已达到预设的最大深度。

以下是使用Python实现ID3算法的一个简单示例:

import numpy as np
import pandas as pd

# 计算熵
def calc_entropy(target_col):
    entropy = -np.sum([len(target_col[target_col == val]) / len(target_col) * np.log2(len(target_col[target_col == val]) / len(target_col))
                       for val in np.unique(target_col)])
    return entropy

# 按照给定属性分裂数据集
def split_dataset(dataset, index, value):
    return dataset[dataset.iloc[:, index] == value]

# 选择最好的数据集属性
def choose_best_feature_to_split(dataset):
    num_features = dataset.shape[1] - 1
    base_entropy = calc_entropy(dataset.iloc[:, -1])
    best_info_gain = 0.0
    best_feature = -1
    for i in range(num_features):
        feat_list = dataset.iloc[:, i]
        unique_vals = set(feat_list)
        new_entropy = 0.0
        for value in unique_vals:
            sub_dataset = split_dataset(dataset, i, value)
            prob = len(sub_dataset) / len(dataset)
            new_entropy += prob * calc_entropy(sub_dataset.iloc[:, -1])
        info_gain = base_entropy - new_entropy
        if info_gain > best_info_gain:
            best_info_gain = info_gain
            best_feature = i
    return best_feature

# 构建决策树
def create_tree(dataset, labels):
    # 检查数据集是否为空
    if len(dataset) == 0:
        return None
    # 检查数据集中的所有目标变量是否相同
    if len(set(dataset.iloc[:, -1])) <= 1:
        return dataset.iloc[0, -1]
    # 检查是否已达到最大深度或者没有更多的特征
    if len(dataset.columns) == 1 or len(set(dataset.iloc[:, -1])) == 1:
        return majority_cnt(dataset.iloc[:, -1])
    # 选择最好的数据集属性
    best_feat = choose_best_feature_to_split(dataset)
    best_feat_label = dataset.columns[best_feat]
    my_tree = {best_feat_label: {}}
    del(dataset[:, best_feat])
    unique_vals = set(dataset.iloc[:, -1])
    for value in unique_vals:
        sub_labels = best_feat_label + "_" + str(value)
        my_tree[best_feat_label][value] = create_tree(split_dataset(dataset, best_feat, value), sub_labels)
    return my_tree

# 找到出现次数最多的目标变量值
def majority_cnt(class_list):
    class_count = {}
    for vote in class_list:
        if vote not in class_count.keys():
            class_count[vote] = 1
        else:
            class_count[vote] += 1
    sorted_class_count = sorted(class_count.items(), key=lambda item: item[1], reverse=True)
    return sorted_class_count[0][0]

# 加载数据集
dataset = pd.read_csv("your_dataset.csv")  # 替换为你的数据集路径
labels = dataset.iloc[:, -1].name
dataset = dataset.iloc[:, 0:-1]  # 特征数据

# 创建决策树
my_tree = create_tree(dataset, labels)
print(my_tree)

:这个实现是为了教学目的而简化的,实际应用中通常会使用更高级的库和算法,如 scikit-learn 中的 DecisionTreeClassifier。


2. C4.5

C4.5是ID3的改进版,使用信息增益比替代信息增益作为特征选择标准,从而克服了ID3倾向于选择多值特征的缺点。此外,C4.5还能处理连续型特征和缺失值

实现C4.5算法可以通过多种编程语言,但这里我将提供一个简化的Python实现,使用Python的基本库来构建决策树。这个实现将包括计算信息熵、信息增益、信息增益比,并基于这些度量来构建决策树。

1. 计算信息熵

信息熵是度量数据集无序程度的指标,计算公式为:

其中 pi  是第 i  个类别的样本在数据集中的比例。

2. 计算信息增益

信息增益是度量在知道特征  A  的条件下,数据集  S  的熵减少的程度。计算公式为:

其中 Sv  是特征  A  值为  v  时的子集。

3. 计算信息增益比

信息增益比是信息增益与特征  A  的固有信息的比值,计算公式为:

其中,分裂信息 Split Information(S, A)  是度量特征  A  的值分布的熵:

4. 构建决策树

使用以上计算方法,我们可以构建一个简单的C4.5决策树:

import numpy as np
import pandas as pd

def entropy(target_col):
    elements, counts = np.unique(target_col, return_counts=True)
    probabilities = counts / counts.sum()
    return -np.sum(probabilities * np.log2(probabilities))

def information_gain(data, feature, target):
    total_entropy = entropy(data[target])
    values = data[feature].unique()
    weighted_entropy = 0.0
    for value in values:
        sub_data = data[data[feature] == value]
        weighted_entropy += (len(sub_data) / len(data)) * entropy(sub_data[target])
    return total_entropy - weighted_entropy

def gain_ratio(data, feature, target):
    ig = information_gain(data, feature, target)
    split_info = entropy(data[feature])
    return ig / split_info if split_info != 0 else 0

def choose_best_feature_to_split(data, features, target):
    best_feature = None
    max_gain_ratio = -1
    for feature in features:
        gain_ratio_value = gain_ratio(data, feature, target)
        if gain_ratio_value > max_gain_ratio:
            max_gain_ratio = gain_ratio_value
            best_feature = feature
    return best_feature

def c45(data, features, target, tree=None, depth=0):
    if len(data[target].unique()) == 1:
        return data[target].mode()[0]
    
    if depth == 0:
        depth = 0
    elif depth > 10:  # Limit the depth to avoid overfitting
        return data[target].mode()[0]
    
    best_feat = choose_best_feature_to_split(data, features, target)
    if best_feat is None:
        return data[target].mode()[0]
    
    if len(data[best_feat].unique()) == 1:
        return data[target].mode()[0]
    
    tree = tree if tree else {best_feat: {}}
    unique_vals = data[best_feat].unique()
    
    for value in unique_vals:
        subtree = c45(data[data[best_feat] == value], features, target, tree=tree, depth=depth+1)
        tree[best_feat][value] = subtree
    return tree

# Example usage
data = pd.DataFrame({
    'Outlook': ['Sunny', 'Sunny', 'Overcast', 'Rain', 'Rain', 'Rain', 'Overcast', 'Sunny', 'Sunny', 'Rain', 'Sunny', 'Overcast', 'Overcast', 'Rain'],
    'Temperature': ['Hot', 'Hot', 'Hot', 'Mild', 'Cool', 'Cool', 'Cool', 'Mild', 'Cool', 'Mild', 'Mild', 'Mild', 'Hot', 'Mild'],
    'Humidity': ['High', 'High', 'High', 'High', 'Normal', 'Normal', 'Normal', 'High', 'Normal', 'Normal', 'Normal', 'High', 'Normal', 'High'],
    'Wind': ['Weak', 'Strong', 'Weak', 'Weak', 'Weak', 'Strong', 'Strong', 'Weak', 'Weak', 'Weak', 'Strong', 'Strong', 'Weak', 'Strong'],
    'PlayTennis': ['No', 'No', 'Yes', 'Yes', 'Yes', 'No', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'No']
})

features = ['Outlook', 'Temperature', 'Humidity', 'Wind']
target = 'PlayTennis'

tree = c45(data, features, target)
print(tree)

注:这个实现是一个简化版,没有包括剪枝和处理连续变量的步骤。在实际应用中,你可能需要使用更复杂的数据结构和算法来优化性能和处理更复杂的情况。


3. CART

CART(分类与回归树)是一种既能用于分类也能用于回归的决策树算法。对于分类问题,CART使用基尼不纯度作为特征选择标准;对于回归问题,则使用方差作为分裂标准。CART构建的是二叉树,每个内部节点都是二元分裂。

以下是CART算法的基本步骤:

1. 选择最佳分割特征和分割点:使用基尼不纯度(Gini impurity)或均方误差(Mean Squared Error, MSE)作为分割标准,选择能够最大程度降低不纯度的特征和分割点。

2. 分割数据集:根据选定的特征和分割点,将数据集分割成两个子集。

3. 递归构建:对每个子集重复步骤1和2,直到满足停止条件(如达到最大深度、节点中的样本数量低于阈值或无法进一步降低不纯度)。

4. 剪枝:通过剪掉树的某些部分来简化树,以防止过拟合。

以下是一个简化的Python实现CART算法,使用基尼不纯度作为分割标准:

import numpy as np
import pandas as pd

def gini_impurity(y):
    class_probabilities = y.mean(axis=0)
    return 1 - np.sum(class_probabilities ** 2)

def best_split(data, target_column, features):
    best_feature = None
    best_threshold = None
    best_gini = float('inf')
    
    for feature in features:
        for idx in np.unique(data[feature]):
            threshold = (data[feature] < idx).mean()
            split_data = data[data[feature] < idx]
            gini = (len(data) - len(split_data)) / len(data) * gini_impurity(split_data[target_column]) + \
                   len(split_data) / len(data) * gini_impurity(data[(data[target_column] == target_column.mode())[data[target_column] >= idx]][target_column])
            if gini < best_gini:
                best_gini = gini
                best_feature = feature
                best_threshold = threshold
    
    return best_feature, best_threshold

def build_tree(data, target_column, features, depth=0, max_depth=None):
    if max_depth is None:
        max_depth = np.inf
    if len(data[target_column].unique()) == 1 or len(data) == 1 or depth >= max_depth:
        return data[target_column].mode()[0]
    
    best_feature, best_threshold = best_split(data, target_column, features)
    tree = {best_feature: {}}
    features = [f for f in features if f != best_feature]
    
    split_function = lambda x: x[best_feature] < best_threshold
    left_indices = np.array([bool(split_function(row)) for row in data.itertuples()])
    right_indices = np.array([not bool(split_function(row)) for row in data.itertuples()])
    
    left_data = data[left_indices]
    right_data = data[right_indices]
    
    if not left_data.empty:
        tree[best_feature][0] = build_tree(left_data, target_column, features, depth+1, max_depth)
    if not right_data.empty:
        tree[best_feature][1] = build_tree(right_data, target_column, features, depth+1, max_depth)
    
    return tree

# Example usage
data = pd.DataFrame({
    'Feature1': [1, 2, 4, 6, 8, 10],
    'Feature2': [2, 4, 6, 8, 10, 12],
    'Target': ['Yes', 'No', 'Yes', 'No', 'Yes', 'No']
})

features = ['Feature1', 'Feature2']
target_column = 'Target'

tree = build_tree(data, target_column, features)
print(tree)

注:这个实现是一个简化的版本,没有包括剪枝步骤。在实际应用中,你可能需要使用更复杂的数据结构和算法来优化性能和处理更复杂的情况。此外,对于回归问题,需要使用均方误差(MSE)而不是基尼不纯度作为分割标准。

在实践中,通常会使用像scikit-learn这样的机器学习库来构建CART树,因为它们提供了更高效和更可靠的实现。例如,scikit-learn中的DecisionTreeClassifier和DecisionTreeRegressor类实现了CART算法。


决策树的优缺点

优点:

- 易于理解和解释。
- 可以处理数值和类别数据。
- 不需要数据标准化。
- 可以可视化。

缺点:

- 容易过拟合。
- 对于某些数据集,构建的树可能非常大。
- 对于缺失数据敏感。

决策树的优化

- 剪枝:通过减少树的大小来减少过拟合。
- 集成方法:如随机森林和梯度提升树,可以提高模型的泛化能力。


执笔至此,感触彼多,全文将至,落笔为终,感谢各位读者的支持,如果对你有所帮助,还请一键三连支持我,我会持续更新创作。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu开机进入紧急模式处理

文章目录 Ubuntu开机进入紧急模式处理一、问题描述二、解决办法参考 Ubuntu开机进入紧急模式处理 一、问题描述 Ubuntu开机不能够正常启动&#xff0c;自动进入紧急模式&#xff08;You are in emergency mode&#xff09;。具体如下所示&#xff1a; 二、解决办法 按CtrlD进…

基于SpringBoot+Vue的智能宾馆预定系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

基于人工智能的实时健身训练分析系统:深蹲姿态识别与动作评估

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色…

前端css样式设置元素的绝对定位和相对定位,要注意宽度和高度的设置

vue3子div position absolute,父div positon relative 。如果不设置子div的 width 和height,那么子div中如果数据变长,子div相对父div位置会变化。子div数据超过&#xff0c;显示... 如何实现 <template><div class"parent"><div class"child&q…

[含文档+PPT+源码等]精品大数据项目-基于Django实现的高校图书馆智能推送系统的设计与实现

大数据项目——基于Django实现的高校图书馆智能推送系统的设计与实现背景&#xff0c;可以从以下几个方面进行详细阐述&#xff1a; 一、信息技术的发展背景 随着信息技术的飞速发展和互联网的广泛普及&#xff0c;大数据已经成为现代社会的重要资源。在大数据背景下&#xf…

深入计算机语言之C++:C到C++的过度

&#x1f511;&#x1f511;博客主页&#xff1a;阿客不是客 &#x1f353;&#x1f353;系列专栏&#xff1a;从C语言到C语言的渐深学习 欢迎来到泊舟小课堂 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 一、什么是C C&#xff08;c plus plus&#xff…

stm32单片机学习 - MDK仿真调试

1 进行环境配置 点击 Options for Target&#xff0c;也就是我们俗称的魔法棒。 将"C/C"中的Optimization选项选为Level 0(-O0) 作用:优化等级调为0级,便于调试时分析代码 勾选"Debug"中的Load Application at Starup 和 Run to main() 选项 作用:Load…

DBeaver详细安装与使用教程-免费的数据库管理工具

一、简介 二、安装教程 三、使用教程 1. 连接MySQL数据库 2. 查看表数据 3. 查看表属性 3. SQL编辑器和控制台 4.在DBeaver中设置定时备份数据库 一、简介 dbeaver是一款的数据库连接工具&#xff0c;免费&#xff0c;跨平台。 官网&#xff1a;DBeaver Community | …

前端——切换轮播图

学完前端js小知识后&#xff0c;动手操作的一个简单图片轮播图。 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"keywords" content"关键词信息"><meta name"des…

数据中心交换机与普通交换机之间的区别到底在哪里?

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 上午好&#xff0c;我的网工朋友。 数据中心交换被设计用来满足数据中心特有的高性能、高可靠性和可扩展性需求。 与此同时&#xff0c;普通交换机…

ACL(Access Control List)访问控制列表

目录 ACL 访问控制列表 ACL分类 ACL的组成 ACL匹配机制 ACL调用方式 实验配置 不允许PC1访问PC4 只允许PC1访问PC4 高级ACL 基本概念 实验配置 限制ping 实验配置 限制DNS 基于时间的ACL 实验配置 ACL 访问控制列表 根据一系列不同的规则&#xff0c;设备根据这…

使用Python实现Auto.js的自动输入图形验证码

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【unity进阶知识6】Resources的使用,如何封装一个Resources资源管理器

文章目录 一、Unity资源加载的几种方式1、Inspector窗口拖拽2、Resources3、AssetBundle4、Addressables&#xff08;可寻址资源系统&#xff09;5、AssetDatabase 二、准备三、同步加载Resources资源1、Resources.Load同步加载单个资源1.1、基本加载1.2、加载指定类型的资源1.…

详解JavaScript中把函数作为值

8.4 作为值的函数 JS中函数不仅是一种语法&#xff0c;也是值&#xff0c;也就是说&#xff0c;可以将函数赋值给变量&#xff0c;存储在对象的属性或者数组的元素中&#xff0c;作为参数传入另外一个函数等。 来看一个函数&#xff1a;function square(x){return x*x;} 定义…

深度学习之入门书籍

自学深度学习&#xff0c;书籍很重要。 从我个人来说&#xff0c;我不太习惯英译版本&#xff0c;或者那些牛人说的&#xff0c;直接读英文&#xff0c;我是水平不够。只讲自己的经验。牛人绕道。 推荐书籍: 深度学习:从入门到精通&#xff0c;这本书不错。把基础的深度学习的…

自然语言处理问答系统技术

自然语言处理问答系统技术 随着人工智能的不断发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;技术已成为推动智能问答系统发展的核心技术。问答系统是利用NLP来解析用户提出的问题&#xff0c;并从知识库中找到最相关的答案。在许多应用中&#xff0c;如智能客服、…

用 LoRA 微调 Stable Diffusion:拆开炼丹炉,动手实现你的第一次 AI 绘画

总得拆开炼丹炉看看是什么样的。这篇文章将带你从代码层面一步步实现 AI 文本生成图像&#xff08;Text-to-Image&#xff09;中的 LoRA 微调过程&#xff0c;你将&#xff1a; 了解 Trigger Words&#xff08;触发词&#xff09;到底是什么&#xff0c;以及它们如何影响生成结…

构建企业数字化转型的战略基石——TOGAF框架的深度解析

数字化时代的企业变革需求 在全球范围内&#xff0c;数字化转型已成为企业提高竞争力、优化运营流程、提升客户体验的核心战略。数字技术的迅猛发展&#xff0c;不仅改变了传统行业的运作模式&#xff0c;也迫使企业重新思考其业务架构和技术基础设施。TOGAF&#xff08;The O…

用示波器测动态滞回线

大学物理&#xff08;下&#xff09;实验-中南民族大学通信工程2022级 手动逐个处理数据较为麻烦且还要绘图&#xff0c;故想到用pythonmatplotlib来计算结果并数据可视化。 代码实现 import matplotlib.pyplot as plt# 样品一磁化曲线 X [0, 0.2, 0.4, 0.6, 0.8, 1, 1.5, 2.…

实战笔记:Vue2项目Webpack 3升级到Webpack 4的实操指南

在Web开发领域&#xff0c;保持技术的更新是非常重要的。随着前端构建工具的快速发展&#xff0c;Webpack已经更新到5.x版本&#xff0c;如果你正在使用Vue2项目&#xff0c;并且还在使用Webpack 3&#xff0c;那么是时候考虑升级一下Webpack了。我最近将我的Vue2项目从Webpack…