机器学习---决策树

📅 2026/8/4 4:56:23
机器学习---决策树
摘要本文系统介绍了决策树的基本概念、构成要素根节点、非叶子节点、叶子节点及其作为有监督学习算法的原理。重点讲解了三种经典决策树分类标准ID3算法基于熵值、C4.5算法基于信息增益比和CART算法基于基尼指数。最后通过一个完整的电信客户流失预测案例详细演示了从数据读取、预处理、模型训练包括交叉验证调参到评估可视化的Python实战流程提供了可直接运行的代码示例。一、什么是决策树以及构成决策树通过对训练样本的学习并建立分类规则然后根据分类规则对新样本数据进行分类预测属于有监督学习。(有监督学习是机器学习的一种核心范式其基本思想是通过已知的输入-输出样本即带标签的数据集来学习一个映射函数使得该函数能够对新的、未知的输入数据做出准确的预测。)决策树包含根节点第一个节点非叶子节点中间节点叶子节点最终结果节点二、决策树的分类标准2.1 ID3算法衡量标准熵值表示随机变量不确定性的度量或者说是物体内部的混乱程度。熵熵值越小该节点越“纯”。熵值的计算公式2.2 C4.5算法算法是一种决策树生成算法它使用信息增益比gain ratio来选择最优分裂属性具体步骤如下1、计算所有样本的类别熵H。2、对于每一个属性计算该属性的熵【也为自身熵】Hi。3、对于每一个属性计算该属性对于分类所能够带来的信息增益Gi H - Hi。4、计算每个属性的信息增益比gain ratio Gi / Hi即信息增益与类别自身熵的比值。选择具有最大信息增益比的属性作为分裂属性。2.3 CART决策树用Gini指数最小化准则来进行特征选择。基于基尼GINI指数决策树的分类只需做了解即可三、决策树的案例分析---某公司客户流失案例3.1数据样例的部分展示数据已上传可进行下载字段说明1.months~move皆是样本的特征2.station为样本的标签3.2 完整流程和代码分步讲解第一步导入pandas读取本地数据import pandas as pd datas pd.read_excel(电信客户流失数据2.xlsx) #将特征与标签分开 data datas.iloc[ : ,: -1] target datas.iloc[ : , -1]对于是用numpy读取还是用pandas读取取决于数据集是否有标题有标题的用pandas读取没有标题的用numpy读取#无标题用numpy import numpy as np data np.loadtxt() #有标题用pandas import pandas as pd datas pd.read_excel()第二步可定义混淆矩阵模型预测的结果可视化让你一眼看出模型在哪些类别上表现好、哪些类别容易分错。混淆矩阵的定义是固定的模板可自行记忆。import matplotlib.pyplot as plt def cm_plot(y,yp): from sklearn.metrics import confusion_matrix import matplotlib.pyplot as plt cm confusion_matrix(y ,yp) plt.matshow(cm , cmap plt.cm.Blues) plt.colorbar() for x in range(len(cm)): for y in range(len(cm)): plt.annotate(cm[x,y],xy(y,x),horizontalalignment center, verticalalignmentcenter) plt.ylabel(True label) plt.xlabel(Predicted label) return plt第三步对数据进行处理#将特征与标签分开 #第一种 data datas.iloc[ : ,: -1] target datas.iloc[ : , -1] #第二种 x data.drop(Class,axis1) y data.Class #Class为对应的标签所在的列 #划分测试集和训练集 from sklearn.model_selection import train_test_split data_train,data_test,target_train,target_test train_test_split(data,target,test_size 0.2,random_state0)第四步定义决策树并通过交叉验证来寻找最优参数的值拿为什么要通过交叉验证验证选参呢因为通过交叉验证从一堆候选参数中找出“泛化能力最好”的那个避免模型过拟合或欠拟合。我们需要一个科学的方法来找到那个“刚刚好”的值而不是靠猜。交叉验证就是干这个的。from sklearn import tree #执行交叉验证,来找寻最优参数 from sklearn.linear_model import LogisticRegression from sklearn.model_selection import cross_val_score #执行交叉验证操作选择比较优的max_depth scores [] #用来存储不同c的验证集下的评分 max_depth_param_range [2, 3, 4, 5, 6, 7, 8, 10]#max_depth的参数 for i in max_depth_param_range: dtr tree.DecisionTreeClassifier(max_depthi,random_state0) score cross_val_score(dtr,data_train,target_train,cv8,scoringaccuracy) score_mean sum(score)/len(score) scores.append(score_mean) print(score_mean) #根据score中最大的值找到对应的max_depth的参数 best_max_depth max_depth_param_range[np.argmax(scores)] print(f............最优的max_depth为{best_max_depth}...........) #执行交叉验证操作选择比较优的min_samples_leaf scores [] #用来存储不同的min_samples_leaf验证集下的评分 min_samples_leaf_param_range [2, 3, 4, 5, 6, 7, 8, 10]#min_samples_leaf的参数 for i in min_samples_leaf_param_range: dtr tree.DecisionTreeClassifier(max_depth best_max_depth ,min_samples_leafi,random_state0) score cross_val_score(dtr,data_train,target_train,cv8,scoringaccuracy) score_mean sum(score)/len(score) scores.append(score_mean) print(score_mean) #根据score中最大的值找到对应的min_samples_leaf的参数 best_min_samples_leaf min_samples_leaf_param_range[np.argmax(scores)] print(f............最优的max_depth为{best_min_samples_leaf}...........)该方法代码是基于初学者便于理解有更简洁优雅的代码可自行优化。第五步训练模型和混淆矩阵的训练#训练模型 dtr tree.DecisionTreeClassifier(max_depth best_max_depth,min_samples_leafbest_min_samples_leaf,random_state0) dtr.fit(data_train,target_train) 训练集混淆矩阵 #训练集预测值 train_predicted dtr.predict(data_train) from sklearn import metrics #绘制混淆矩阵 print(metrics.classification_report(target_train,train_predicted)) #可视化混淆矩阵 cm_plot(target_train,train_predicted).show() 测试集混淆矩阵 test_predicted dtr.predict(data_test) from sklearn import metrics #绘制混淆矩阵 print(metrics.classification_report(target_test,test_predicted)) #可视化矩阵 cm_plot(target_test,test_predicted).show()第六步对决策树进行评分#对决策树进行评分 dtr.score(data_test,target_test) from sklearn.tree import plot_tree fig ,ax plt.subplots(figsize(32,32)) plot_tree(dtr,filled True,ax ax) plt.show()完整代码为import pandas as pd import matplotlib.pyplot as plt from pylab import mpl import numpy as np def cm_plot(y,yp): from sklearn.metrics import confusion_matrix import matplotlib.pyplot as plt cm confusion_matrix(y ,yp) plt.matshow(cm , cmap plt.cm.Blues) plt.colorbar() for x in range(len(cm)): for y in range(len(cm)): plt.annotate(cm[x,y],xy(y,x),horizontalalignment center, verticalalignmentcenter) plt.ylabel(True label) plt.xlabel(Predicted label) return plt datas pd.read_excel(电信客户流失数据2.xlsx) #将特征与标签分开 data datas.iloc[ : ,: -1] target datas.iloc[ : , -1] #划分测试集和训练集 from sklearn.model_selection import train_test_split data_train,data_test,target_train,target_test train_test_split(data,target,test_size 0.2,random_state0) #定义决策树 from sklearn import tree #执行交叉验证,来找寻最优参数 from sklearn.model_selection import cross_val_score #执行交叉验证操作选择比较优的max_depth scores [] #用来存储不同c的验证集下的评分 max_depth_param_range [2, 3, 4, 5, 6, 7, 8, 10]#max_depth的参数 for i in max_depth_param_range: dtr tree.DecisionTreeClassifier(max_depthi,random_state0) score cross_val_score(dtr,data_train,target_train,cv8,scoringaccuracy) score_mean sum(score)/len(score) scores.append(score_mean) print(score_mean) #根据score中最大的值找到对应的max_depth的参数 best_max_depth max_depth_param_range[np.argmax(scores)] print(f............最优的max_depth为{best_max_depth}...........) #执行交叉验证操作选择比较优的min_samples_leaf scores [] #用来存储不同的min_samples_leaf验证集下的评分 min_samples_leaf_param_range [2, 3, 4, 5, 6, 7, 8, 10]#min_samples的参数 for i in min_samples_leaf_param_range: dtr tree.DecisionTreeClassifier(max_depth best_max_depth ,min_samples_leafi,random_state0) score cross_val_score(dtr,data_train,target_train,cv8,scoringaccuracy) score_mean sum(score)/len(score) scores.append(score_mean) print(score_mean) #根据score中最大的值找到对应的min_samples_leaf的参数 best_min_samples_leaf min_samples_leaf_param_range[np.argmax(scores)] print(f............最优的max_depth为{best_min_samples_leaf}...........) dtr tree.DecisionTreeClassifier(max_depth best_max_depth,min_samples_leafbest_min_samples_leaf,random_state0) dtr.fit(data_train,target_train) 训练集混淆矩阵 #训练集预测值 train_predicted dtr.predict(data_train) from sklearn import metrics #绘制混淆矩阵 print(metrics.classification_report(target_train,train_predicted)) #可视化混淆矩阵 cm_plot(target_train,train_predicted).show() 测试集混淆矩阵 test_predicted dtr.predict(data_test) from sklearn import metrics #绘制混淆矩阵 print(metrics.classification_report(target_test,test_predicted)) #可视化矩阵 cm_plot(target_test,test_predicted).show() #对决策树进行评分 dtr.score(data_test,target_test) from sklearn.tree import plot_tree fig ,ax plt.subplots(figsize(32,32)) plot_tree(dtr,filled True,ax ax) plt.show()四、决策树的优缺点与适用场景决策树作为一种经典的机器学习算法因其直观、易于理解和实现而广受欢迎。然而它也存在一些固有的局限性。本节将系统总结决策树的主要优点、缺点以及典型的适用场景。4.1 优点可解释性强决策树生成的规则if-then非常直观易于向非技术人员解释符合人类的决策思维过程。无需数据标准化决策树不依赖于数据的距离或度量因此不需要对数据进行标准化或归一化处理可以直接处理原始数据。能够处理混合类型数据既可以处理数值型特征也可以处理类别型特征。对缺失值不敏感大多数决策树算法如CART能够通过代理分裂等技术处理缺失值。可以捕捉特征间的非线性关系通过树的分裂过程能够自然地建模特征之间的交互作用和非线性关系。计算复杂度相对较低训练和预测的速度通常较快适合处理大规模数据集。4.2 缺点容易过拟合如果不进行剪枝或设置深度限制决策树倾向于生成非常复杂的树完美拟合训练数据导致在测试集上泛化能力差。对数据变化敏感训练数据的微小变化可能导致生成完全不同的树结构高方差不够稳定。倾向于选择具有更多取值的特征信息增益等准则会偏好具有更多类别的特征可能导致偏差。难以学习复杂的关系对于需要复杂边界如XOR问题或高度线性可分的数据决策树可能不是最优选择性能可能不如支持向量机或神经网络。可能产生有偏的树如果类别分布不平衡生成的树可能会偏向于多数类。4.3 适用场景需要模型可解释性的场景如金融风控、医疗诊断、商业决策等决策者需要理解模型做出判断的依据。探索性数据分析决策树可以帮助快速识别数据中最重要的特征和潜在的模式。作为复杂模型的基准由于其简单和快速常被用作与其他更复杂模型如随机森林、梯度提升树对比的基准模型。集成学习的基础组件决策树是随机森林、梯度提升决策树GBDT、XGBoost、LightGBM等强大集成模型的核心弱学习器。处理混合数据类型当数据集同时包含数值和类别特征时决策树是一个方便的选择。在实际应用中为了克服单一决策树的缺点通常会使用集成方法如随机森林、梯度提升树来提升模型的稳定性、准确性和泛化能力。