基于python的决策树分类原理与代码实例(代码直接复制粘贴)

帮忙点赞评论一番,以满足我的虚荣心[狗头.jpg]


目录

1 决策树分类模型原理

1.1 基本原理

1.1.1 信息增益(Information Gain)

1.1.2 基尼系数(Gini Index)

1.2 决策树生成算法

1. 2.1 ID3算法

1.2.2 C4.5算法

1.2.2.1信息增益比的计算

1.2.2.2 C4.5算法的主要步骤

1.2.3 CART算法

1.3 决策树剪枝

1.3.1 后剪枝(Post-pruning)

1.3.2预剪枝(Pre-pruning)

1.3.3 剪枝的权衡

1.4 总结

2 代码

2.1 导入必要的库

2.2 加载数据与数据预处理

2.3 划分数据集 

2.4 训练模型

2.5 可视化决策树

2.5.1 matplotlob库

2.5.2 graph库

2.6 预测

2.7模型评估

2.7.1 模型评估报告

2.7.2 K折交叉验证


1 决策树分类模型原理

        决策树分类模型是机器学习中一种常用的分类算法,它通过构建一个树形结构来实现对数据集的分类。这种模型的核心思想是将数据集按照其属性特征进行递归划分,直到满足一定的终止条件,形成一棵决策树。决策树由结点和有向边组成,其中结点分为内部结点和叶结点两种类型,内部结点表示一个特征或属性,而叶结点则表示一个类别。决策树可以被视为一系列if-then规则的集合,从根节点到叶结点的每一条路径都构建了一条规则,路径上的内部结点特征对应规则的条件,叶结点的类别对应规则的结论。

1.1 基本原理

决策树算法的主要目的是通过选择最优的属性来对数据集进行划分,以达到最佳的分类效果。这个最优属性的选择通常依赖于一些度量标准,如信息增益、基尼系数等。

1.1.1 信息增益(Information Gain)

        信息增益是决策树算法中用于选择最优划分属性的一个重要标准。它基于信息熵(Entropy)的概念,信息熵是度量样本集合纯度最常用的一种指标。假设样本集合D中第k类样本所占的比例为p_{k}(k=1,2,...,N),则D的信息熵定义为:

Ent(D) = -\sum_{k=1}^{N} p_k \log_2 p_k

信息熵的值越小,表示D的纯度越高。给定属性A,我们可以计算条件熵H(D∣A),即在属性A的条件下,数据集D的经验条件熵。条件熵的计算公式为:

H(D|A) = \sum_{v=1}^{V} \frac{|D^v|}{|D|} Ent(D^v)

其中,D^{v}表示在属性A上取值为v的样本子集,v是属性A的可能取值个数。

        信息增益IG(D,A)则是数据集D的经验熵H(D)与条件熵H(D∣A)之差,即:

 IG(D,A) = H(D) - H(D|A)

信息增益越大,表示使用属性A进行划分所获得的纯度提升越大,因此,选择信息增益最大的属性作为最优划分属性。

1.1.2 基尼系数(Gini Index)

        基尼系数也是决策树算法中常用的一个划分标准,尤其在CART(Classification and Regression Trees)算法中广泛使用。基尼系数用于度量数据集D的纯度,其定义如下:

Gini(D) = \sum_{k=1}^{|Y|} \sum_{k' \neq k} p_k p_{k'} = 1 - \sum_{k=1}^{|Y|} p_k^2 

其中,∣Y∣表示数据集D中不同类别的个数,pk​表示数据集D中属于第k个类别的样本占总样本数的比例。基尼系数的值越小,表示数据集D的纯度越高。

        对于属性A,我们可以计算基尼系数GiniA​(D),即按照属性A的不同取值对数据集D进行划分后的基尼系数加权和:

Gini_A(D) = \sum_{v=1}^{V} \frac{|D^v|}{|D|} Gini(D^v)

选择基尼系数最小的属性作为最优划分属性。

1.2 决策树生成算法

        决策树的生成算法主要包括特征选择、决策树的生成和决策树的修剪三个步骤。常用的算法有ID3、C4.5和CART。

1. 2.1 ID3算法

        ID3算法是最早的决策树生成算法之一,它使用信息增益作为选择最优划分属性的标准。ID3算法的主要步骤如下:

  1. 初始化:从根节点开始,数据集为D。
  2. 特征选择:计算数据集D中每个属性的信息增益,选择信息增益最大的属性作为最优划分属性。
  3. 划分数据集:根据最优划分属性的不同取值,将数据集D划分为若干个子集。
  4. 递归生成:对每个子集递归执行步骤2和步骤3,直到满足停止条件(如子集只包含一类样本或达到预设的树深度)。
  5. 生成叶结点:如果当前子集只包含一类样本,则生成一个叶结点,并将其类别标记为该样本的类别。
1.2.2 C4.5算法

        C4.5算法在ID3算法的基础上,引入了信息增益比(Gain Ratio)作为选择最优划分属性的标准。信息增益比克服了信息增益在选择属性时偏向于选择取值数目较多属性的不足。

1.2.2.1信息增益比的计算

        信息增益比的计算首先要求出属性A的固有值(Intrinsic Value)或称为分裂信息(Split Information):

SplitInfo(D, A) = -\sum_{v=1}^{V} \frac{|D^v|}{|D|} \log_2 \frac{|D^v|}{|D|}

其中,Dv表示在属性A上取值为v的样本子集,V是属性A的可能取值个数。然后,信息增益比GainRatio(D,A)定义为信息增益IG(D,A)与属性A的固有值SplitInfo(D,A)之比:

GainRatio(D, A) = \frac{IG(D, A)}{SplitInfo(D, A)}

        注意,如果某个属性A的取值数目较多,则SplitInfo(D,A)的值会较大,导致GainRatio(D,A)的值较小。这样,信息增益比就在一定程度上避免了信息增益的偏好问题。

1.2.2.2 C4.5算法的主要步骤

C4.5算法的主要步骤与ID3算法类似,但在特征选择阶段使用信息增益比代替信息增益:

  1. 初始化:从根节点开始,数据集为D。
  2. 特征选择:计算数据集D中每个属性的信息增益比,选择信息增益比最大的属性作为最优划分属性。
  3. 划分数据集:根据最优划分属性的不同取值,将数据集D划分为若干个子集。
  4. 递归生成:对每个子集递归执行步骤2和步骤3,直到满足停止条件(如子集只包含一类样本、达到预设的树深度或信息增益比小于预设阈值)。
  5. 生成叶结点:如果当前子集只包含一类样本,则生成一个叶结点,并将其类别标记为该样本的类别。

        C4.5算法还通过剪枝技术来避免过拟合问题,提高模型的泛化能力。

1.2.3 CART算法

        CART(Classification and Regression Trees)算法是一种既可以用于分类也可以用于回归的决策树算法。在分类任务中,CART使用基尼系数作为选择最优划分属性的标准。

CART算法的主要步骤(分类任务):

  1. 初始化:从根节点开始,数据集为D。
  2. 特征选择:计算数据集D中每个属性的基尼系数,选择基尼系数最小的属性作为最优划分属性。
  3. 划分数据集:根据最优划分属性的不同取值,将数据集D划分为若干个子集。
  4. 递归生成:对每个子集递归执行步骤2和步骤3,直到满足停止条件(如子集只包含一类样本、达到预设的树深度或基尼系数减小量小于预设阈值)。
  5. 生成叶结点:如果当前子集只包含一类样本,则生成一个叶结点,并将其类别标记为该样本的类别。

        CART算法生成的决策树是二叉树,即每次划分都是将数据集划分为两个子集。对于具有多个取值的属性,CART算法通常采用某种策略(如使用属性值的某个中位数或众数)来将属性值划分为两个子集。

1.3 决策树剪枝

        剪枝是决策树学习中防止过拟合、提高模型泛化能力的重要手段。剪枝通过简化决策树的结构来减少模型的复杂度,使得模型在未知数据上的表现更加稳定。

1.3.1 后剪枝(Post-pruning)

        后剪枝是一种在决策树完全生长之后,再对其进行剪枝的方法。其步骤如下:

  1. 从底部开始:首先,将决策树中最底层的非叶结点视为候选结点。
  2. 评估剪枝效果:对于每个候选结点,尝试将其替换为其子树中最常见的类别(即将其转化为叶结点),并评估这一剪枝操作对模型性能的影响。这通常通过交叉验证在验证集上进行,比较剪枝前后的误差率或准确率等指标。
  3. 剪枝决策:如果剪枝操作能够提升模型的泛化能力(即验证集上的性能有所提升),则进行剪枝。
  4. 递归剪枝:将剪枝后的结点视为新的候选结点,重复步骤2和步骤3,直到无法进一步提升模型性能为止。

        后剪枝的优点在于其能够保留更多的分支,因此可能具有更好的分类效果。然而,其计算量相对较大,因为需要对每个非叶结点都进行剪枝评估。

1.3.2预剪枝(Pre-pruning)

        预剪枝则是在决策树生成过程中,提前停止树的生长,从而避免生成过于复杂的树结构。其策略包括:

  1. 设置最大深度:在生成决策树之前,指定树的最大深度。当树达到这个深度时,停止生长。
  2. 限制节点样本数:如果某个节点的样本数少于预设的阈值,则停止该节点的进一步划分。
  3. 限制信息增益(或基尼系数减小量):如果某个节点的划分带来的信息增益(或基尼系数减小量)小于预设的阈值,则不进行划分,该节点成为叶结点。

        预剪枝的优点在于其计算量相对较小,因为决策树在生成过程中就进行了剪枝。然而,预剪枝可能导致模型欠拟合,因为某些可能重要的分支可能由于未达到剪枝条件而被提前终止。

1.3.3 剪枝的权衡

        剪枝是一个权衡过程,需要在模型的复杂度和泛化能力之间找到最佳平衡点。过少的剪枝可能导致模型过拟合,即在训练集上表现良好但在测试集上表现不佳;而过多的剪枝则可能导致模型欠拟合,即模型过于简单,无法充分捕捉数据中的复杂关系。

        在实际应用中,可以通过交叉验证等方法来评估不同剪枝策略对模型性能的影响,从而选择最合适的剪枝方法。此外,还可以结合使用预剪枝和后剪枝技术,以进一步提高模型的性能。

1.4 总结

        决策树分类模型通过构建树形结构来实现对数据集的分类。其核心在于选择最优的划分属性来递归地划分数据集,直到满足一定的停止条件。在生成决策树的过程中,需要采用信息增益、基尼系数等度量标准来选择最优属性。为了防止过拟合,还需要对生成的决策树进行剪枝处理。剪枝方法包括预剪枝和后剪枝两种,各有优缺点,需要根据实际情况选择使用。通过合理的剪枝策略,可以提高决策树模型的泛化能力,使其在实际应用中更加有效。

2 代码

2.1 导入必要的库

import pandas as pd  
from sklearn.model_selection import train_test_split, cross_val_score, KFold  
from sklearn.tree import DecisionTreeClassifier  
from sklearn.metrics import confusion_matrix, classification_report, accuracy_score  
from sklearn.model_selection import RandomizedSearchCV  
from skopt import BayesSearchCV  
from skopt.space import Real, Categorical, Integer  
from sklearn.tree import plot_tree  
import matplotlib.pyplot as plt  
import seaborn as sns  
# 忽略Matplotlib的警告(可选)  
import warnings  
warnings.filterwarnings("ignore") 
# 设置中文显示和负号正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

2.2 加载数据与数据预处理

# 加载数据  
df = pd.read_excel('目标客户体验数据.xlsx')  
df.fillna(0, inplace=True)  
df.dtypes

2.3 划分数据集 

# 假设 'isorno' 是目标列,其余为特征  
X = df.iloc[:, :-1]  # 所有行,除了最后一列  
y = df.iloc[:, -1]   # 所有行的最后一列   
  
# 划分数据集  
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=42) 

2.4 训练模型

# 创建决策树模型  
clf = DecisionTreeClassifier(random_state=42)  
clf.fit(X_train, y_train)  

2.5 可视化决策树

2.5.1 matplotlob库
# 可视化决策树  
plt.figure(figsize=(20,10))  
plot_tree(clf, filled=True, feature_names=X_train.columns, class_names=['No', 'Yes'], rounded=True)  
plt.show()  
  

        可视化结果如图5-1所示:

图5-1 决策树树状图

2.5.2 graph库

        使用graph库可能会有报错:未安装graph库,安装方法可以参考别人的贴子。

from sklearn.tree import DecisionTreeClassifier, export_graphviz  
import graphviz  
feature_names = ['id', 'style', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'B1',
       'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10', 'B11', 'B12',
       'B13', 'B14', 'B15', 'B16', 'B17'] # 获取特征名  
target_names = ['0','1']    # 获取类别名  
# 导出决策树为 .dot 文件(这里我们直接渲染,不保存到文件)  
dot_data = export_graphviz(clf, out_file=None,   
                           feature_names=feature_names,  
                           class_names=target_names,  
                           filled=True, rounded=True,  
                           special_characters=True)  
  
# 使用 graphviz 渲染 .dot 数据  
graph = graphviz.Source(dot_data)  
# 如果你在 Jupyter Notebook 中,可以直接显示图形  
graph
graph.render("decision_tree", format="png")

        可视化结果如图5-2所示:

图5-2  决策树树状图

2.6 预测

  
# 预测并评估  
y_pred = clf.predict(X_test)  
 

2.7模型评估

2.7.1 模型评估报告
print(confusion_matrix(y_test, y_pred))  
print(classification_report(y_test, y_pred)) 
[[182   4]
 [  4   7]]
              precision    recall  f1-score   support

           0       0.98      0.98      0.98       186
           1       0.64      0.64      0.64        11

    accuracy                           0.96       197
   macro avg       0.81      0.81      0.81       197
weighted avg       0.96      0.96      0.96       197
2.7.2 K折交叉验证
from sklearn.model_selection import cross_validate, KFold    
from sklearn.ensemble import RandomForestClassifier    
import numpy as np    
import matplotlib.pyplot as plt    
 
# 设置 k_values    
k_values = range(2, 21)  # 从 2 开始,因为 KFold 需要至少 2 个折叠    
  
# 用于存储结果的列表    
accuracies = []    
recalls = []    
f1_scores = []    
  
for k in k_values:    
    kf = KFold(n_splits=k, shuffle=True, random_state=42)    
    results = cross_validate(clf, X, y, cv=kf, scoring=['accuracy', 'recall', 'f1'], return_train_score=False)    
    accuracies.append(results['test_accuracy'].mean())    
    recalls.append(results['test_recall'].mean())    
    f1_scores.append(results['test_f1'].mean())    
  
# 找到每个列表中的最大值及其索引  
max_acc_idx = accuracies.index(max(accuracies))  
max_recall_idx = recalls.index(max(recalls))  
max_f1_idx = f1_scores.index(max(f1_scores))   
# 绘制图形  
plt.figure(figsize=(12, 6))    
  
# 绘制准确率  
plt.subplot(1, 3, 1)    
plt.plot(k_values, accuracies, color='black',marker='o')    
plt.xlabel('Number of folds')    
plt.ylabel('Average Accuracy')    
plt.title('Accuracy vs. Number of Folds')
plt.xticks(np.arange(0, 21,1))
plt.grid(True) 
plt.annotate(f'X: {max_acc_idx:.0f}', (k_values[max_acc_idx], max(accuracies)), textcoords="offset points", xytext=(-15,7), ha='center')  
plt.annotate(f'Max: {max(accuracies):.4f}', (k_values[max_acc_idx], max(accuracies)), textcoords="offset points", xytext=(30,7), ha='center')  
plt.axhline(y=max(accuracies), color='r', linestyle='--')  
plt.axvline(x=k_values[max_acc_idx], color='deepskyblue', linestyle='--')
# 绘制召回率  
plt.subplot(1, 3, 2)     
plt.plot(k_values, recalls, color='orange', marker='o')    
plt.xlabel('Number of folds')    
plt.ylabel('Average Recall')    
plt.title('Recall vs. Number of Folds') 
plt.xticks(np.arange(0, 21, 1))
plt.grid(True)  
plt.annotate(f'X: {max_recall_idx:.0f}', (k_values[max_recall_idx], max(recalls)), textcoords="offset points", xytext=(-15,7), ha='center')  
plt.annotate(f'Max: {max(recalls):.4f}', (k_values[max_recall_idx], max(recalls)), textcoords="offset points", xytext=(30,7), ha='center')  
plt.axhline(y=max(recalls), color='r', linestyle='--')  
plt.axvline(x=k_values[max_recall_idx], color='deepskyblue', linestyle='--')
# 绘制 F1 分数  
plt.subplot(1, 3, 3)      
plt.plot(k_values, f1_scores, color='g', marker='o')    
plt.xlabel('Number of folds')    
plt.ylabel('Average F1 Score')    
plt.title('F1 Score vs. Number of Folds')
plt.xticks(np.arange(0, 21, 1))
plt.grid(True) 
plt.annotate(f'X: {max_f1_idx:.0f}', (k_values[max_acc_idx], max(f1_scores)), textcoords="offset points", xytext=(-15,7), ha='center') 
plt.annotate(f'Max: {max(f1_scores):.4f}', (k_values[max_f1_idx], max(f1_scores)), textcoords="offset points", xytext=(30,7), ha='center')  
plt.axhline(y=max(f1_scores), color='r', linestyle='--')  
plt.axvline(x=k_values[max_f1_idx], color='deepskyblue', linestyle='--') 
plt.tight_layout()  # 调整子图参数, 使之填充整个图像区域  
plt.show()

        可视化结果如图7-2所示:

图7-2 不同K值模型性能对比

Vivado2023是一款集成开发环境软件,用于设计和验证FPGA(现场可编程门阵列)和可编程逻辑器件。对于使用Vivado2023的用户来说,license是必不可少的。 Vivado2023的license是一种许可证,用于授权用户合法使用该软件。许可证分为多种类型,包括评估许可证、开发许可证和节点许可证等。每种许可证都有不同的使用条件和功能。 评估许可证是免费提供的,让用户可以在一段时间内试用Vivado2023的全部功能。用户可以使用这个许可证来了解软件的性能和特点,对于初学者和小规模项目来说是一个很好的选择。但是,使用评估许可证的用户在使用期限过后需要购买正式的许可证才能继续使用软件。 开发许可证是付费的,可以永久使用Vivado2023的全部功能。这种许可证适用于需要长期使用Vivado2023进行开发的用户,通常是专业的FPGA设计师或工程师。购买开发许可证可以享受Vivado2023的技术支持和更新服务,确保软件始终保持最新的版本和功能。 节点许可证是用于多设备或分布式设计的许可证,可以在多个计算机上安装Vivado2023,并共享使用。节点许可证适用于大规模项目或需要多个处理节点进行设计的用户,可以提高工作效率和资源利用率。 总之,Vivado2023 license是用户在使用Vivado2023时必须考虑的问题。用户可以根据自己的需求选择合适的许可证类型,以便获取最佳的软件使用体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值