数学建模学习-决策树(Decision Tree)教程
创作时间:
作者:
@小白创作中心
数学建模学习-决策树(Decision Tree)教程
引用
CSDN
1.
https://blog.csdn.net/FFMXjy/article/details/145219407
决策树是一种基于树结构的监督学习算法,它通过一系列问题将数据集划分为不同的子集,最终得到一个能够对新数据进行分类或回归预测的模型。本文将通过一个户外活动适宜性预测的例子,详细介绍决策树模型的训练和可视化过程,并提供完整的代码示例。
算法简介
决策树是一种基于树结构的监督学习算法,它通过一系列问题将数据集划分为不同的子集,最终得到一个能够对新数据进行分类或回归预测的模型。决策树的结构类似于流程图,从根节点开始,通过不同的分支到达叶节点,每个叶节点代表一个预测结果。
决策树的基本原理是通过信息增益(Information Gain)、基尼指数(Gini Index)或其他指标来选择最优的特征和分割点,将数据集划分为更纯净的子集。这个过程递归进行,直到达到停止条件(如最大深度、最小样本数等)。
算法特点
优点:
- 直观易懂:决策树的结构类似于人类的决策过程,易于理解和解释
- 无需特征缩放:决策树对特征的尺度不敏感
- 可处理数值和类别特征:能同时处理不同类型的特征
- 自动进行特征选择:通过特征重要性可以了解各个特征的影响力
- 计算效率高:训练和预测速度都较快
缺点:
- 容易过拟合:需要通过剪枝等方法来控制模型复杂度
- 不稳定性:数据微小的变化可能导致树的结构发生较大变化
- 局部最优:在每个节点上的分割都是局部最优的,可能无法得到全局最优解
- 偏向于占主导地位的类:在类别不平衡的数据集上可能表现不佳
环境准备
本教程需要以下Python库:
numpy>=1.21.0
pandas>=1.3.0
scikit-learn>=0.24.2
matplotlib>=3.4.2
graphviz>=0.17
可以通过以下命令安装:
pip install -r requirements.txt
代码实现
数据准备
在本教程中,我们创建了一个关于户外活动适宜性的数据集,包含温度、湿度和风速三个特征:
def create_weather_data():
"""创建天气数据集"""
data = {
'温度': np.random.uniform(10, 35, 100),
'湿度': np.random.uniform(30, 90, 100),
'风速': np.random.uniform(0, 30, 100)
}
df = pd.DataFrame(data)
# 根据条件生成标签
conditions = []
for temp, humidity, wind in zip(df['温度'], df['湿度'], df['风速']):
if temp > 30 and humidity > 70:
conditions.append('不适宜')
elif wind > 25:
conditions.append('不适宜')
elif temp < 15:
conditions.append('不适宜')
else:
conditions.append('适宜')
df['户外活动'] = conditions
return df
模型训练
使用scikit-learn库中的DecisionTreeClassifier进行模型训练:
# 准备特征和标签
X = df[['温度', '湿度', '风速']]
y = df['户外活动']
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建并训练决策树模型
dt_classifier = DecisionTreeClassifier(max_depth=3, random_state=42)
dt_classifier.fit(X_train, y_train)
结果可视化
我们提供了多个可视化方法来帮助理解决策树模型:
- 决策树结构可视化
plt.figure(figsize=(20,10))
plot_tree(dt_classifier, feature_names=['温度', '湿度', '风速'],
class_names=['适宜', '不适宜'], filled=True, rounded=True)
plt.savefig('images/decision_tree.png', dpi=300, bbox_inches='tight')
- 特征重要性分析
plt.figure(figsize=(10,6))
importances = dt_classifier.feature_importances_
features = ['温度', '湿度', '风速']
plt.bar(features, importances)
plt.title('特征重要性分析')
plt.xlabel('特征')
plt.ylabel('重要性')
- 数据分布可视化
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
for i, feature in enumerate(features):
axes[i].hist(df[feature], bins=20)
axes[i].set_title(f'{feature}分布')
- 决策边界可视化
plt.figure(figsize=(10,8))
temp_range = np.linspace(df['温度'].min(), df['温度'].max(), 100)
humidity_range = np.linspace(df['湿度'].min(), df['湿度'].max(), 100)
xx, yy = np.meshgrid(temp_range, humidity_range)
实例分析
在本例中,我们构建了一个户外活动适宜性预测模型。从结果可以看出:
- 模型性能:
- 准确率达到80%
- 对"适宜"和"不适宜"两类的预测都较为平衡
- 精确率和召回率都在可接受范围内
- 特征重要性:
- 温度是最重要的特征,这与我们的直觉相符
- 风速次之,对活动适宜性有显著影响
- 湿度的影响相对较小
- 决策边界:
- 可以清晰地看到不同区域的分类结果
- 边界的形状反映了决策树的分段线性特性
- 部分区域的分类结果较为明确,而边界区域的分类相对模糊
全部代码如下:
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, classification_report
from sklearn.preprocessing import LabelEncoder
import os
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建示例数据
def create_weather_data():
"""创建天气数据集"""
data = {
'温度': np.random.uniform(10, 35, 100),
'湿度': np.random.uniform(30, 90, 100),
'风速': np.random.uniform(0, 30, 100)
}
df = pd.DataFrame(data)
# 根据条件生成标签
conditions = []
for temp, humidity, wind in zip(df['温度'], df['湿度'], df['风速']):
if temp > 30 and humidity > 70:
conditions.append('不适宜')
elif wind > 25:
conditions.append('不适宜')
elif temp < 15:
conditions.append('不适宜')
else:
conditions.append('适宜')
df['户外活动'] = conditions
return df
# 生成数据
df = create_weather_data()
# 准备特征和标签
X = df[['温度', '湿度', '风速']]
# 使用LabelEncoder将标签转换为数值
le = LabelEncoder()
y = le.fit_transform(df['户外活动'])
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建并训练决策树模型
dt_classifier = DecisionTreeClassifier(max_depth=3, random_state=42)
dt_classifier.fit(X_train, y_train)
# 在测试集上进行预测
y_pred = dt_classifier.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy:.2f}")
# 打印分类报告
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=['适宜', '不适宜']))
# 创建图片保存目录
if not os.path.exists('images'):
os.makedirs('images')
# 可视化决策树
plt.figure(figsize=(20,10))
plot_tree(dt_classifier, feature_names=['温度', '湿度', '风速'],
class_names=['适宜', '不适宜'], filled=True, rounded=True)
plt.savefig('images/decision_tree.png', dpi=300, bbox_inches='tight')
plt.close()
# 特征重要性可视化
plt.figure(figsize=(10,6))
importances = dt_classifier.feature_importances_
features = ['温度', '湿度', '风速']
plt.bar(features, importances)
plt.title('特征重要性分析')
plt.xlabel('特征')
plt.ylabel('重要性')
plt.savefig('images/feature_importance.png', dpi=300, bbox_inches='tight')
plt.close()
# 数据分布可视化
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
for i, feature in enumerate(features):
axes[i].hist(df[feature], bins=20)
axes[i].set_title(f'{feature}分布')
axes[i].set_xlabel(feature)
axes[i].set_ylabel('频数')
plt.tight_layout()
plt.savefig('images/data_distribution.png', dpi=300, bbox_inches='tight')
plt.close()
# 决策边界可视化(使用温度和湿度两个特征)
plt.figure(figsize=(10,8))
# 创建网格
temp_min, temp_max = df['温度'].min() - 1, df['温度'].max() + 1
humidity_min, humidity_max = df['湿度'].min() - 1, df['湿度'].max() + 1
temp_range = np.linspace(temp_min, temp_max, 100)
humidity_range = np.linspace(humidity_min, humidity_max, 100)
xx, yy = np.meshgrid(temp_range, humidity_range)
# 使用平均风速值进行预测
avg_wind = df['风速'].mean()
mesh_features = np.column_stack([xx.ravel(), yy.ravel(),
np.full(xx.ravel().shape, avg_wind)])
# 预测
Z = dt_classifier.predict(mesh_features).reshape(xx.shape)
# 绘制决策边界
plt.contourf(xx, yy, Z, alpha=0.4, cmap='RdYlBu')
scatter = plt.scatter(df['温度'], df['湿度'], c=y,
cmap='RdYlBu', alpha=0.8)
plt.colorbar(scatter, label='预测类别')
plt.xlabel('温度')
plt.ylabel('湿度')
plt.title('决策边界可视化')
plt.savefig('images/decision_boundary.png', dpi=300, bbox_inches='tight')
plt.close()
总结与思考
应用建议
- 特征选择:
- 选择与目标变量相关性强的特征
- 避免使用冗余特征
- 考虑特征之间的交互作用
- 参数调优:
- 合理设置树的深度(max_depth)
- 调整最小样本数(min_samples_split, min_samples_leaf)
- 使用交叉验证选择最优参数
- 模型评估:
- 不仅关注整体准确率
- 考虑各类别的精确率和召回率
- 分析混淆矩阵了解模型的具体表现
实际应用中的注意事项
- 数据预处理:
- 处理缺失值
- 处理异常值
- 适当的特征工程
- 模型优化:
- 考虑使用集成方法(如随机森林、梯度提升树)
- 处理类别不平衡问题
- 定期更新模型以适应新数据
- 结果解释:
- 结合领域知识解释模型决策
- 注意模型的局限性
- 考虑模型的可解释性需求
扩展思考
- 与其他算法的比较:
- 决策树vs线性模型
- 决策树vs神经网络
- 在不同场景下的适用性
- 高级技巧:
- 特征重要性分析
- 交叉验证
- 模型集成
- 实际应用场景:
- 金融风控
- 医疗诊断
- 工业生产
- 自然语言处理
热门推荐
中美AI竞争最新态势:美国保持领先,中国加速追赶
Excel高手教你快速搞定英文日期格式
美式VS英式日期格式:英语沟通中的选择指南
Excel快速设置英文日期格式,办公效率up up!
重磅楼市新政公布 房地产板块飙升 这只龙头股市盈率不足10倍
华夏幸福的开盘情况如何?这种开盘情况受哪些因素影响?
北京房价跌了,现在是买房的好时机吗?
北京房产市场回暖,买房正当时?
草长莺飞二月天,高鼎《村居》里的春日乡村画卷
黄鳝养殖的秘密武器——养殖蚯蚓
双金属结构加动感全息,2025蛇年纪念币钞防伪技术大揭秘
新型玻璃离子水门汀:兼具安全、美观与耐用的补牙黑科技
女龙宝宝取名带“涵”字好不好?
现代简约 vs 地中海:谁更适合你的阳台卧室?
卧室带阳台,风水布局大揭秘!
带阳台卧室设计,让你的家更温馨舒适
NASA月球探测器发现水冰,为建立月球基地提供可能
澳大利亚科学家发现:火星引力以240万年周期影响地球气候
240万年周期,火星引力影响地球气候获证实
科学家发现:火星引力每240万年影响地球气候一次
悉尼大学研究:火星引力引发地球气候240万年周期变化
重庆人口大变局:21万人大幅流失背后
人口激增下的城市之困:交通、住房、环境如何破局?
人口流动新趋势:从“孔雀东南飞”到“中西部回流”
焦作怀山药:补肾益精的养生圣品,食用搭配全攻略
山药红枣变饮品,山药藜麦做沙拉:怀山药的花样新吃法
活力四射的白羊座:解码他们的外貌特征与社交技巧
胰腺癌术后饮食全攻略:四阶段恢复方案详解
巨蟹天蝎双鱼:水象星座男生素来感性,外貌只是第一印象
十二星座十二张脸:从白羊到双鱼的外貌特征