XGBoost案例之红酒品质分类-数据预处理
1 课程概览
本课使用XGBoost完成红酒品质分类案例的数据预处理部分。红酒数据集有3269条数据,11个特征,6个类别(多分类)。本课重点处理数据不均衡问题。
2 核心概念与定义
- 红酒品质分类:多分类问题,6个类别。
- 数据不均衡:某些类别样本多,某些类别样本少。
- stratify:分层抽样,参考Y轴比例。
- softmax:多分类的激活函数。
- 数据预处理:加载、切分、保存。
3 算法与模型详解
3.1 案例背景
数据集:红酒品质分类
- 数据量:3269条
- 特征数:11个
- 类别数:6个(多分类)
- 标签:最后一列(从3开始:3、4、5、6、7、8)
问题:
- 多分类问题(6个类别)
- 数据样本不均衡(3、4、5类别占多数,6、7、8类别占少数)
3.2 XGBoost多分类
说明:XGBoost不仅能做二分类,也能做多分类
目标函数:softmax
3.3 数据不均衡处理
问题:3000多条数据中,3、4、5类别占了3000条,6、7、8类别只有几百条
解决方案:权重平衡(后续讲解)
3.4 标签处理
问题:标签从3开始(3、4、5、6、7、8)
处理:减3,转为0、1、2、3、4、5
3.5 数据集划分
参数:
test_size:测试集比例random_state:随机种子stratify=y:参考Y轴比例,防止数据失衡
3.6 数据保存
目的:
- 训练时直接读取,不用每次切分
- 预测时直接读取测试集
3.7 案例拆分
三个视频:
- 数据预处理(本课)
- 模型训练
- 模型使用(joblib保存和加载)
4 代码示例
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
# 1. 加载数据
print("=== 加载红酒数据 ===")
data = pd.read_csv('data/winequality.csv')
print(f"数据形状: {data.shape}")
print(f"\n前5行:")
print(data.head())
print(f"\n列名: {data.columns.tolist()}")
# 2. 提取特征和标签
print("\n=== 提取特征和标签 ===")
# 最后一列是标签,其他是特征
X = data.iloc[:, :-1]
y = data.iloc[:, -1]
print(f"特征形状: {X.shape}")
print(f"标签形状: {y.shape}")
print(f"\n标签分布:")
print(y.value_counts().sort_index())
# 3. 标签处理(减3,转为0-5)
print("\n=== 标签处理 ===")
print(f"原始标签: {sorted(y.unique())}")
y = y - 3
print(f"处理后标签: {sorted(y.unique())}")
print(f"\n处理后标签分布:")
print(y.value_counts().sort_index())
# 4. 划分数据集
print("\n=== 划分数据集 ===")
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
random_state=22,
stratify=y # 分层抽样,参考Y轴比例
)
print(f"训练集: {X_train.shape}")
print(f"测试集: {X_test.shape}")
# 5. 查看分层效果
print("\n=== 分层抽样效果 ===")
print("训练集标签分布:")
print(y_train.value_counts().sort_index())
print("\n测试集标签分布:")
print(y_test.value_counts().sort_index())
# 6. 保存数据集
print("\n=== 保存数据集 ===")
# 训练集
train_data = X_train.copy()
train_data['label'] = y_train
train_data.to_csv('data/wine_train.csv', index=False)
print(f"训练集已保存: {train_data.shape}")
# 测试集
test_data = X_test.copy()
test_data['label'] = y_test
test_data.to_csv('data/wine_test.csv', index=False)
print(f"测试集已保存: {test_data.shape}")
# 7. 数据探索
print("\n=== 数据探索 ===")
print(f"特征统计:")
print(X.describe())
# 8. 检查缺失值
print("\n=== 检查缺失值 ===")
print(f"特征缺失值:")
print(X.isnull().sum())
# 9. 特征相关性
print("\n=== 特征相关性 ===")
correlation = X.corr()
print("特征相关性矩阵(前5x5):")
print(correlation.iloc[:5, :5])
# 10. 可视化准备
print("\n=== 数据可视化准备 ===")
import matplotlib.pyplot as plt
# 标签分布
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 原始标签分布
axes[0].bar(y_train.value_counts().sort_index().index,
y_train.value_counts().sort_index().values)
axes[0].set_title('训练集标签分布')
axes[0].set_xlabel('类别')
axes[0].set_ylabel('数量')
# 测试集标签分布
axes[1].bar(y_test.value_counts().sort_index().index,
y_test.value_counts().sort_index().values)
axes[1].set_title('测试集标签分布')
axes[1].set_xlabel('类别')
axes[1].set_ylabel('数量')
plt.tight_layout()
plt.savefig('data/label_distribution.png', dpi=100)
print("标签分布图已保存")
# 11. 完整流程函数
def preprocess_wine_data(input_path, output_dir='data'):
"""红酒数据预处理完整流程"""
print("=" * 50)
print("红酒品质分类 - 数据预处理")
print("=" * 50)
# 1. 加载数据
data = pd.read_csv(input_path)
print(f"1. 加载数据: {data.shape}")
# 2. 提取特征和标签
X = data.iloc[:, :-1]
y = data.iloc[:, -1]
print(f"2. 特征: {X.shape}, 标签: {y.shape}")
# 3. 标签处理
y = y - 3 # 转为0-5
print(f"3. 标签处理: {sorted(y.unique())}")
# 4. 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
random_state=22,
stratify=y
)
print(f"4. 划分数据集: 训练{X_train.shape}, 测试{X_test.shape}")
# 5. 保存
train_data = X_train.copy()
train_data['label'] = y_train
train_data.to_csv(f'{output_dir}/wine_train.csv', index=False)
test_data = X_test.copy()
test_data['label'] = y_test
test_data.to_csv(f'{output_dir}/wine_test.csv', index=False)
print(f"5. 数据已保存")
print("\n预处理完成!")
return X_train, X_test, y_train, y_test
# 运行
# X_train, X_test, y_train, y_test = preprocess_wine_data('data/winequality.csv')
输出示例:
=== 加载红酒数据 ===
数据形状: (3269, 12)
前5行:
fixed acidity volatile acidity ... alcohol quality
0 7.4 0.70 ... 9.4 5
1 7.8 0.88 ... 9.8 5
...
=== 提取特征和标签 ===
特征形状: (3269, 11)
标签形状: (3269,)
标签分布:
3 20
4 163
5 1547
6 1260
7 240
8 39
Name: quality, dtype: int64
=== 标签处理 ===
原始标签: [3, 4, 5, 6, 7, 8]
处理后标签: [0, 1, 2, 3, 4, 5]
=== 划分数据集 ===
训练集: (2615, 11)
测试集: (654, 11)
=== 分层抽样效果 ===
训练集标签分布:
0 16
1 130
2 1238
3 1008
4 192
5 31
测试集标签分布:
0 4
1 33
2 309
3 252
4 48
5 8
=== 保存数据集 ===
训练集已保存: (2615, 12)
测试集已保存: (654, 12)
5 重难点与易错提醒
- ❗重点:红酒品质是多分类问题(6个类别)。
- ❗重点:数据样本不均衡,需要处理。
- ❗重点:标签从3开始,需要减3转为0-5。
- ❗重点:stratify=y分层抽样,防止数据失衡。
- ⚠️易错:忘记减3导致标签不从0开始。
- ⚠️易错:忘记stratify参数导致数据失衡。
- 💡深入理解:保存数据集方便后续训练和预测。
6 课堂问答精选
Q: 为什么要对标签减3?
A: 原始标签从3开始(3、4、5、6、7、8),减3后转为0、1、2、3、4、5。这是因为大多数机器学习算法期望标签从0开始,便于索引和计算。
Q: stratify参数有什么作用?
A: stratify=y表示在划分数据集时参考Y轴(标签)的比例,确保训练集和测试集的标签分布相似,防止数据失衡。例如,如果原始数据中类别5占47%,则训练集和测试集中类别5也约占47%。
7 本课小结
- 红酒数据:3269条,11特征,6类别。
- 多分类问题:使用softmax。
- 数据不均衡:后续使用权重平衡。
- 标签处理:减3转为0-5。
- 分层抽样:stratify=y。
- 数据保存:方便后续训练和预测。
8 延伸思考与实践
- 实践:运行红酒数据预处理代码。
- 预习:XGBoost模型训练。
- 思考:如何处理数据不均衡问题?