系列文章目录
第一章:Pyhton机器学习算法之KNN
第二章:Pyhton机器学习算法之K—Means
第三章:Pyhton机器学习算法之随机森林
第四章:Pyhton机器学习算法之线性回归
第五章:Pyhton机器学习算法之有监督学习与无监督学习
第六章:Pyhton机器学习算法之决策树
目录
前言
决策树是一种简单直观的机器学习算法,用于做分类或回归任务。它就像我们平常做决定时的过程,逐步排除可能的选项,最终得出结论。这是一种在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,从而评价项目风险并判断其可行性的决策分析方法。同时,在机器学习中,决策树也是一个重要的预测模型。以下是对决策树的详细解释:
一、基本原理:
-
定义:决策树是一种采用树状结构描述功能模块逻辑处理过程的结构化语言表现形式,通过直观的图形方式表达条件、决策规则和应采取的行动之间的逻辑关系。
-
结构:决策树由节点和边组成,形成一个树状结构。其中,每个内部节点表示一个属性或特征上,每个分支代表一个特征值,每个叶节点代表一种类别或预测结果。
3.决策树的三部分:
①根节点:开始时,将整个数据集作为一个根节点。选择一个特征,将数据集分成多个子集。特征的选择基于信息增益、基尼系数或均方误差等进行选择
②内部节点:将上面得到的每个根节点的子集都视为一个分支节点,并在分支节点上选择领一个特征,再次将分支节点分成多个更小的子集,如此递归下去,直到某些停止条件:最大树深、节点中样本小于阈值或者基尼不纯度低于阈值。
③叶子节点:当数据集不再进行分割,节点就会被标记为叶子节点,叶子节点中包含一个最终的类别标签(分类问题)或者回归值(回归问题)。类别是根据数据集的主要类别确定的,而回归值主要是根据平均目标值确定的。
4.决策树的预测原理:
构建决策树后,输入新样本,从根节点开始根据样本特征的值遍历树的分支,直到叶子节点,然后将叶子节点的类别标签或者回归值作为结果返回。
例如:
我们需要做一个“今天要不要带伞”的决策。
第一个问题(根节点):今天是否下雨?
——如果答案是「会下雨」,那就带伞(这是一个叶节点,表示决策已经做完)
——如果答案是「不下雨」,则继续进行第二个问题
第二个问题(内部节点):今天是否多云?
——如果答案是「多云」,那就继续问第三个问题
——如果答案是「晴天」,那就不带伞(这是另一个叶节点,决策做完)
第三个问题(内部节点):今天路程远近?
——如果答案是「远」,为了安全起见,带伞
——如果答案是「近」,不带伞
今天会下雨吗?
/ \
是 否
带伞 今天多云吗?
/ \
是 否
今天走很远吗? 不带伞
/ \
是 否
带伞 不带伞
简单来说,决策树就是一个一步步问问题、逐步排除不相关选项、最后做出决定的过程。它是一种很直观的分类或预测工具,像我们平常做决定时的逻辑一样。
二、特征划分准则:
特征选择:
决策树的学习过程主要涉及信息增益和基尼系数,用于选择最佳的分裂特征
也可以用selcetkbest进行重要特征选择,代码如下:
from sklearn.feature_selection import SelectKBest, chi2
# 选择K个最佳特征
X = data.drop('target', axis=1)
y = data['target']
X_new = SelectKBest(chi2, k=5).fit_transform(X, y)
1.1信息增益(Information Gain):
用于衡量某个特征在数据划分中所带来的信息量,是分类问题中常见的划分准则。每个节点上,根据特征取值将数据集分成多个子集,计算每个子集的熵,然后计算信息增益(即父节点熵与子节点熵之差),熵越高,表示系统越混乱,而信息增益越大,证明划分之后的节点更纯净。选择信息增益大的特征作为划分特征。
熵是衡量数据不确定性的指标。熵越高,系统越混乱。熵的公式如下:
其中, pi表示第 i类的概率。对于一个包含 n 个类别的集合 S,我们通过计算每个类别的概率,然后带入熵公式得到不确定性的大小。
信息增益反映了某个特征能够带来的熵的减少。信息增益公式:
其中,H(S) 是原始数据集的熵, A是我们划分数据的某个特征,Values(A) 是特征A的所有可能取值,而Sv 是通过特征A取值v划分后的子集。
1.2基尼系数(Gini Index):
基尼不纯度作为分类问题的另一个标准,是指将来自集合中的某种结果随机应用在集合中某一数据项的预期误差率。在每个节点上,特征取值将数据集分成多个子集,然计算每个子集的基尼系数,表示从该子集中随机选择两个样本,他们类别不一致的概率,基尼系数越低,则子节点的纯度越高。选择基尼系数最低的特征作为划分特征。
基尼不纯度相较于信息增益更加倾向于选择取值较少的特征,因此在某些情况下,可能对多分类问题更加有利。
基尼指数来衡量划分的纯度,公式如下:
其中 pi表示第 i 类的概率
1.3均方误差:
均方误差是用于回归问题的划分上的准则,是反映估计量与被估计量之间差异程度的一种度量。在每个节点上,根据特征的取值将数据集划分成多个子集,然后计算每个子集的目标变量的均方误差,均方误差越低,表示子节点目标变量更接近均值,模型对数据的拟合程度就越好。选择均方误差最低的特征作为划分特征。
均方误差的公式如下:
三、避免过拟合:
决策树如果过度适应训练集的噪声和细节,导致模型在面对新数据的时候泛化能力过差(即在模型训练集上误差很低,但是在测试集上误差很高),那么我们需要多决策树方法操作,避免这些现象发生。
①剪枝:剪枝可以帮助减少树的复杂程度,通过移除一些叶子节点或者将一些子树替换为叶子节点来降低模型的复杂程度。剪枝的关键是确定何时停止分裂节点以及选择要剪枝的节点。常见的剪枝策略为预剪枝和后剪枝。预剪枝在树生长过程中提前停止,而后剪枝则在树完全生长后再进行修剪
所以,以下②③④⑤均属于预剪枝
以下是后剪枝的代码实现:
import numpy as np
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier, export_text
from sklearn.tree import CostComplexityPruningPath
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 加载数据集
iris = load_iris()
X, y = iris.data, iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 训练决策树模型,设置max_depth=None以允许树完全生长
clf = DecisionTreeClassifier(random_state=42)
clf.fit(X_train, y_train)
# 使用CostComplexityPruningPath找到最佳的剪枝参数
path = CostComplexityPruningPath(clf, X_train, y_train)
ccp_alphas = path.ccp_alphas_
impurities = path.impurities_
# 选择一系列alpha值来评估剪枝后的模型
clfs = []
for ccp_alpha in ccp_alphas:
clf = DecisionTreeClassifier(random_state=42, ccp_alpha=ccp_alpha)
clf.fit(X_train, y_train)
clfs.append(clf)
# 评估每个剪枝后的模型在测试集上的表现
train_scores = [clf.score(X_train, y_train) for clf in clfs]
test_scores = [clf.score(X_test, y_test) for clf in clfs]
# 找到最佳的剪枝参数(例如,最高的测试集准确率)
best_index = np.argmax(test_scores)
best_ccp_alpha = ccp_alphas[best_index]
best_clf = clfs[best_index]
# 输出最佳剪枝后的决策树结构
print(export_text(best_clf, feature_names=iris.feature_names))
# 在测试集上评估最佳剪枝后的模型
y_pred = best_clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
以下是预剪枝的代码实现:
import numpy as np
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import export_text
# 加载数据集
iris = load_iris()
X, y = iris.data, iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 设置预剪枝参数
# max_depth: 树的最大深度
# min_samples_split: 分裂内部节点所需的最小样本数
# min_samples_leaf: 叶节点所需的最小样本数
# min_impurity_decrease: 分裂节点时所需的最小不纯度减少量
pre_pruned_clf = DecisionTreeClassifier(
max_depth=3, # 限制树的最大深度为3
min_samples_split=4, # 每个节点至少包含4个样本才能分裂
min_samples_leaf=2, # 每个叶节点至少包含2个样本
min_impurity_decrease=0.01, # 分裂节点时,不纯度至少需要减少0.01
random_state=42
)
#若criterion='entropy' 则是以信息增益为标准;若criterion='Gini'则是以基尼不纯度度作为标准
# 训练决策树模型
pre_pruned_clf.fit(X_train, y_train)
# 在测试集上评估模型
y_pred = pre_pruned_clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy on test set with pre-pruning: {accuracy:.4f}")
# 输出预剪枝后的决策树结构
print("Pre-pruned tree structure:")
print(export_text(pre_pruned_clf, feature_names=iris.feature_names))
②限制树深:通过设置树的最大深度来控制输的复杂程度
③增加叶子节点最小样本数:通过设置每个叶子节点上的最小样本数,可以控制叶子节点的数量。增加最小样本数量可以防止生成过细的叶子结点
④限制叶子节点最小样本数:与上条相似,但是这里是限制,需要提前设置限制条件
⑤降低信息增益的阈值:降低信息增益的阈值可以使得模型更加保守,确保叶子节点中样本数量不会太少
⑥构建随机森林
四、完整案例:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
import seaborn as sns
# 生成虚拟数据集
np.random.seed(0)
data_size = 1000
X = np.random.rand(data_size, 2)
y = (X[:, 0] + X[:, 1] > 1).astype(int) # 设定一个简单的规则作为目标变量
# 创建DataFrame
df = pd.DataFrame(X, columns=['Feature1', 'Feature2'])
df['Target'] = y
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
# 训练决策树
clf = DecisionTreeClassifier(criterion='entropy', max_depth=3, random_state=0)
clf.fit(X_train, y_train)
# 预测
y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
# 混淆矩阵
conf_matrix = confusion_matrix(y_test, y_pred)
# 绘制决策树
plt.figure(figsize=(12, 8))
plot_tree(clf, filled=True, feature_names=['Feature1', 'Feature2'], class_names=['0', '1'], rounded=True)
plt.title('Decision Tree Visualization')
效果如下:
# 绘制数据点及决策边界
plt.figure(figsize=(12, 8))
xx,yy = np.meshgrid(np.linspace(0, 1, 100), np.linspace(0, 1, 100))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.3, cmap='coolwarm')
plt.scatter(X[:, 0], X[:, 1],c=y, edgecolor='k', cmap='coolwarm')
plt.xlabel('Feature1')
plt.ylabel('Feature2')
plt.title('Decision Boundary and Data Points')
plt.colorbar()
效果如下:
# 打印准确率和分类报告
print(f'Accuracy: {accuracy:.2f}')
print('Confusion Matrix:')
print(conf_matrix)
print('Classification Report:')
print(classification_report(y_test, y_pred))
五、优缺点:
优点
-
简单直观,易于理解和解释
-
适用于处理分类和回归任务
-
可以处理缺失值和不平衡数据
-
对于非线性关系具有良好的适应性
缺点及其解决方案
-
易于过拟合:可以通过剪枝、集成学习等方法解决
-
对于小数据集,结果可能不稳定:可以通过交叉验证和重采样技术提高稳定性
-
不适用于高维稀疏数据:可以使用特征选择和降维技术解决
六、应用范围:
1)商业与经济领域
-
金融风险管理:决策树可以用来评估贷款申请的风险,通过分析申请人的信用历史、收入水平、职业稳定性等信息,预测贷款违约的可能性,从而帮助银行做出是否批准贷款的决策。此外,它还可以用于企业信用评级、投资决策分析等方面。
-
市场营销:企业可以通过收集和分析消费者的购买历史、浏览行为等数据,构建决策树模型,以预测消费者的购买倾向。基于这些预测,企业可以更精准地定位目标客户,制定个性化的营销策略,提高营销效果和客户满意度。
-
供应链管理:在供应商选择、库存管理等方面,决策树可以帮助企业优化供应链流程,降低成本,提高效率。
2)医疗与健康领域
-
医疗诊断:医生可以利用决策树来辅助诊断,通过输入病人的症状、体征、实验室检查结果等信息,决策树能够帮助医生识别出最可能的疾病,并提供相应的治疗建议。此外,它还可以用于疾病预测、患者风险评估等方面。
-
公共卫生管理:决策树可以用于评估不同公共卫生措施的效果,帮助公共卫生管理者制定科学的防控策略。
3)环境与生态领域
决策树可以用于评估不同管理措施对环境的影响。例如,通过分析工业排放、交通流量等因素对空气质量的影响,决策树能够帮助管理者识别出最有效的减排措施,从而制定出科学的环境保护政策。此外,它还可以用于生态风险评估、生物多样性保护等方面。
4)制造与工程领域
-
项目风险评估:通过构建分类决策树,可以根据项目的各个属性(如项目团队经验、施工环境、材料质量等),判断项目是否具有风险。
-
质量控制:决策树可以用于产品质量控制,通过分析生产过程中的各种因素,预测产品的质量水平,从而采取相应的改进措施。
-
生产优化:在制造过程中,决策树可以帮助企业优化生产计划、降低生产成本、提高生产效率。
5)教育与科研领域
-
学生分类与辅导:在教育领域,决策树可以用于学生分类与辅导,通过分析学生的学习成绩、兴趣爱好等因素,为学生提供个性化的辅导方案。
-
科研成果评估:在科研领域,决策树可以用于科研成果的评估与预测,帮助科研人员更好地把握研究方向和趋势。
6)其他领域
决策树还被广泛应用于天文学、分支生物学、法律判决、人力资源管理等多个领域。例如,在法律领域,决策树可以用于案件分类、判决预测等方面;在人力资源管理领域,决策树可以用于员工绩效评估、人才选拔等方面。
7)机器学习与数据挖掘
在机器学习与数据挖掘领域,决策树作为一种直观且强大的分类与回归方法,受到了广泛的关注与应用。它可以处理连续值和离散值数据,对异常点具有良好的容错能力。虽然决策树存在一些缺点(如容易过拟合、对样本变化敏感等),但通过剪枝、集成学习等方法进行改进后,其性能可以得到显著提升。
总结
综上所述,决策树的应用范围十分广泛,涉及商业、医疗、环境、制造、教育、科研以及机器学习与数据挖掘等多个领域。它能够帮助决策者清晰地看到各种决策路径及其可能的结果,从而做出更加合理的决策。