共计 2755 个字符,预计需要花费 7 分钟才能阅读完成。
背景介绍
红葡萄酒数据集是经典的分类任务数据集,包含 11 个理化特征(如酒精含量、酸度等)和 1 个目标变量(质量评分 3 - 8 分)。建模目标是通过理化指标预测葡萄酒质量等级。该数据集特点包括:

- 特征均为数值型,无需独热编码
- 样本量适中(约 1600 条),适合快速验证模型
- 类别分布不均衡,需注意评估指标选择
数据预处理
关键步骤包括缺失值处理、特征缩放和数据集划分:
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
# 加载数据
data = pd.read_csv('winequality-red.csv')
# 检查缺失值
print(data.isnull().sum()) # 本数据集无缺失值
# 特征与标签分离
X = data.drop('quality', axis=1)
y = data['quality']
# 标准化特征(树模型可不做,但为统一流程保留)scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 划分训练集测试集(7:3)X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3, random_state=42)
模型训练
决策树实现
from sklearn.tree import DecisionTreeClassifier
# 基础决策树(关键参数说明)dtree = DecisionTreeClassifier(
max_depth=5, # 控制树深度防过拟合
min_samples_split=10, # 节点最小样本数
criterion='gini', # 分裂标准
random_state=42
)
dtree.fit(X_train, y_train)
随机森林实现
from sklearn.ensemble import RandomForestClassifier
# 基础随机森林(关键参数说明)rf = RandomForestClassifier(
n_estimators=100, # 树的数量
max_features='sqrt', # 每棵树考虑的特征数
max_depth=7, # 单棵树最大深度
random_state=42
)
rf.fit(X_train, y_train)
评估指标详解
多分类任务需采用宏平均(macro)或加权平均(weighted):
from sklearn.metrics import (
accuracy_score, precision_score,
recall_score, f1_score
)
# 决策树评估
y_pred_dtree = dtree.predict(X_test)
print(f"决策树准确率: {accuracy_score(y_test, y_pred_dtree):.3f}")
print(f"加权精确率: {precision_score(y_test, y_pred_dtree, average='weighted'):.3f}")
print(f"加权召回率: {recall_score(y_test, y_pred_dtree, average='weighted'):.3f}")
print(f"加权 F1 值: {f1_score(y_test, y_pred_dtree, average='weighted'):.3f}")
# 随机森林评估(代码结构相同,略)
指标说明:
1. 准确率 :正确预测占总样本的比例
2. 精确率 :预测为正类的样本中实际为正类的比例
3. 召回率 :实际为正类的样本中被正确预测的比例
4. F1 值 :精确率和召回率的调和平均数
结果可视化
混淆矩阵
import matplotlib.pyplot as plt
from sklearn.metrics import ConfusionMatrixDisplay
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5))
ConfusionMatrixDisplay.from_estimator(dtree, X_test, y_test, ax=ax1, cmap='Blues')
ax1.set_title('Decision Tree')
ConfusionMatrixDisplay.from_estimator(rf, X_test, y_test, ax=ax2, cmap='Greens')
ax2.set_title('Random Forest')
plt.show()
ROC 曲线(需二分类转换)
from sklearn.metrics import RocCurveDisplay
from sklearn.preprocessing import label_binarize
# 将多类标签转为二分类形式
y_test_bin = label_binarize(y_test, classes=[3,4,5,6,7,8])
# 绘制每类的 ROC 曲线
fig, ax = plt.subplots(figsize=(8, 6))
for i in range(6):
RocCurveDisplay.from_estimator(rf, X_test, y_test_bin[:, i],
name=f'Class {i+3}', ax=ax)
plt.plot([0, 1], [0, 1], 'k--')
plt.show()
避坑指南
常见问题 1:忽略类别不平衡
- 现象 :高准确率但少数类识别差
- 解决 :采用加权指标或过采样技术(如 SMOTE)
常见问题 2:过度依赖单一指标
- 现象 :只关注准确率忽略其他指标
- 解决 :综合观察 F1 值和混淆矩阵
常见问题 3:测试集信息泄露
- 现象 :预处理时在整个数据集上 fit
- 解决 :确保 scaler 只在训练集上 fit
进阶建议
-
特征重要性分析 :
importances = rf.feature_importances_ feat_importances = pd.Series(importances, index=X.columns) feat_importances.nlargest(5).plot(kind='barh') -
超参数调优 :使用 GridSearchCV 搜索最佳参数组合
- 模型融合 :尝试 Stacking 等集成方法
思考题
- 当某个质量等级样本量极少时,应该如何处理?
- 为什么随机森林的 max_features 参数通常设为特征数的平方根?
- 如何设计自定义评估指标来满足特定业务需求?
通过本实战可以看到,随机森林在大多数指标上优于单棵决策树,尤其在处理类别不平衡时表现更稳定。建议在实践中始终结合多种评估方式,避免陷入单一指标的误区。
正文完
