共计 3720 个字符,预计需要花费 10 分钟才能阅读完成。
背景介绍
红酒分类是机器学习中经典的分类问题,通过分析红酒的化学成分(如酒精含量、苹果酸浓度等)来预测其质量等级。这个问题在品酒行业有重要应用价值,比如自动化质量控制、分级定价等。

对于初学者来说,红酒数据集(Wine Dataset)是一个理想的入门选择,因为它:
- 特征数量适中(13 个化学特征)
- 样本量适中(178 个样本)
- 分类目标明确(3 个类别)
环境准备
首先需要安装 Anaconda,这是一个集成了 Python 和常用数据科学库的发行版。安装完成后,我们需要确保以下库已正确安装:
- pandas:用于数据处理和分析
- scikit-learn:包含决策树等机器学习算法
- matplotlib:用于数据可视化和模型结果展示
可以通过以下命令安装这些库(如果尚未安装):
conda install pandas scikit-learn matplotlib
数据预处理
数据加载
scikit-learn 内置了红酒数据集,我们可以直接加载:
from sklearn.datasets import load_wine
wine_data = load_wine()
探索性分析 (EDA)
在构建模型前,我们需要了解数据的基本情况:
- 查看数据描述:
print(wine_data.DESCR) - 检查特征名称:
print(wine_data.feature_names) - 查看目标类别:
print(wine_data.target_names)
特征工程
虽然红酒数据集已经较为干净,但我们仍需要进行一些基本处理:
- 将数据和标签转换为 DataFrame 格式
- 检查缺失值
- 标准化特征(可选,决策树通常不需要)
模型构建
数据拆分
首先将数据分为训练集和测试集:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(wine_data.data, wine_data.target, test_size=0.2, random_state=42)
决策树分类器
创建并训练决策树模型:
from sklearn.tree import DecisionTreeClassifier
dtree = DecisionTreeClassifier(criterion='gini', max_depth=3, random_state=42)
dtree.fit(X_train, y_train)
关键参数说明:
criterion:分裂标准,’gini’ 表示基尼不纯度,’entropy’ 表示信息增益max_depth:树的最大深度,用于控制模型复杂度random_state:随机种子,确保结果可复现
模型评估
准确率评估
计算模型在测试集上的准确率:
from sklearn.metrics import accuracy_score
y_pred = dtree.predict(X_test)
print("Accuracy:", accuracy_score(y_test, y_pred))
混淆矩阵
更详细的性能评估可以使用混淆矩阵:
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('True')
plt.show()
可视化
决策树可视化
我们可以将决策树结构可视化,便于理解模型决策过程:
from sklearn.tree import plot_tree
plt.figure(figsize=(20,10))
plot_tree(dtree, feature_names=wine_data.feature_names, class_names=wine_data.target_names, filled=True)
plt.show()
特征重要性
查看哪些特征对分类贡献最大:
importances = dtree.feature_importances_
indices = np.argsort(importances)[::-1]
plt.figure(figsize=(10,6))
plt.title("Feature Importances")
plt.bar(range(X_train.shape[1]), importances[indices], align="center")
plt.xticks(range(X_train.shape[1]), wine_data.feature_names[indices], rotation=90)
plt.xlim([-1, X_train.shape[1]])
plt.show()
避坑指南
过拟合问题
决策树容易过拟合,表现为训练集准确率高但测试集准确率低。解决方法:
- 限制树的最大深度(
max_depth) - 设置最小样本分裂数(
min_samples_split) - 设置叶节点最小样本数(
min_samples_leaf) - 使用剪枝(
ccp_alpha参数)
特征量纲不统一
虽然决策树对特征尺度不敏感,但某些情况下标准化可能有助于提升性能。可以使用:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
完整代码示例
以下是完整的 Python 代码,包含所有上述步骤:
# 导入必要库
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
# 加载数据
wine_data = load_wine()
# 数据拆分
X_train, X_test, y_train, y_test = train_test_split(wine_data.data, wine_data.target, test_size=0.2, random_state=42)
# 创建并训练模型
dtree = DecisionTreeClassifier(criterion='gini', max_depth=3, random_state=42)
dtree.fit(X_train, y_train)
# 模型评估
y_pred = dtree.predict(X_test)
print("Accuracy:", accuracy_score(y_test, y_pred))
# 混淆矩阵
cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('True')
plt.show()
# 决策树可视化
plt.figure(figsize=(20,10))
plot_tree(dtree, feature_names=wine_data.feature_names, class_names=wine_data.target_names, filled=True)
plt.show()
# 特征重要性
importances = dtree.feature_importances_
indices = np.argsort(importances)[::-1]
plt.figure(figsize=(10,6))
plt.title("Feature Importances")
plt.bar(range(X_train.shape[1]), importances[indices], align="center")
plt.xticks(range(X_train.shape[1]), wine_data.feature_names[indices], rotation=90)
plt.xlim([-1, X_train.shape[1]])
plt.show()
扩展思考
- 如何调整参数来平衡模型的偏差和方差?
- 除了准确率,还有哪些指标适合评估多分类问题?
- 如何将这个模型部署为 REST API 服务?
- 尝试使用网格搜索(GridSearchCV)自动寻找最优参数组合
- 比较决策树与其他分类算法(如随机森林、SVM)在红酒数据集上的表现
正文完
