XGBoost案例之红酒品质分类-模型训练
1 课程概览
本课使用XGBoost完成红酒品质分类的模型训练部分。重点处理样本不均衡问题,使用compute_sample_weight平衡权重,并保存训练好的模型。
2 核心概念与定义
- compute_sample_weight:平衡权重函数。
- balanced:自动调整权重,平衡样本分布。
- class_weight:类权重参数。
- 模型保存:joblib.dump。
3 算法与模型详解
3.1 训练流程
- 加载训练集和测试集
- 提取特征和标签
- 创建模型对象
- 平衡权重(处理样本不均衡)
- 训练模型
- 评估模型
- 保存模型
3.2 样本不均衡处理
问题:红酒数据样本不均衡(3、4、5类别多,6、7、8类别少)
解决方案:使用compute_sample_weight
函数:
from sklearn.utils.class_weight import compute_sample_weight
sample_weight = compute_sample_weight(class_weight='balanced', y=y_train)
参数:
class_weight='balanced':自动平衡权重y=y_train:参考标签数据分布
3.3 XGBoost分类器
导包:
import xgboost as xgb
创建模型:
xgb.XGBClassifier()
注意:因为导包是import xgboost as xgb,所以使用时要加xgb.前缀
3.4 模型保存
import joblib
joblib.dump(model, 'model.pkl')
4 代码示例
import pandas as pd
import numpy as np
import xgboost as xgb
from sklearn.utils.class_weight import compute_sample_weight
from sklearn.metrics import accuracy_score, classification_report
import joblib
# 1. 加载数据
def load_data():
"""加载训练集和测试集"""
print("=== 加载数据 ===")
train_data = pd.read_csv('data/wine_train.csv')
test_data = pd.read_csv('data/wine_test.csv')
print(f"训练集: {train_data.shape}")
print(f"测试集: {test_data.shape}")
return train_data, test_data
# 2. 提取特征和标签
def extract_features_labels(train_data, test_data):
"""提取特征和标签"""
print("\n=== 提取特征和标签 ===")
# 最后一列是标签,其他是特征
X_train = train_data.iloc[:, :-1]
y_train = train_data.iloc[:, -1]
X_test = test_data.iloc[:, :-1]
y_test = test_data.iloc[:, -1]
print(f"训练集特征: {X_train.shape}, 标签: {y_train.shape}")
print(f"测试集特征: {X_test.shape}, 标签: {y_test.shape}")
return X_train, X_test, y_train, y_test
# 3. 平衡权重
def balance_weights(y_train):
"""平衡权重(处理样本不均衡)"""
print("\n=== 平衡权重 ===")
sample_weight = compute_sample_weight(
class_weight='balanced',
y=y_train
)
print(f"样本权重形状: {sample_weight.shape}")
print(f"样本权重范围: {sample_weight.min():.4f} - {sample_weight.max():.4f}")
# 查看各类别权重
unique_classes = np.unique(y_train)
for cls in unique_classes:
mask = y_train == cls
avg_weight = np.mean(sample_weight[mask])
count = np.sum(mask)
print(f" 类别{cls}: 样本数={count}, 平均权重={avg_weight:.4f}")
return sample_weight
# 4. 创建和训练模型
def train_model(X_train, y_train, sample_weight):
"""创建和训练模型"""
print("\n=== 创建和训练模型 ===")
# 创建XGBoost分类器
model = xgb.XGBClassifier(
n_estimators=100,
max_depth=6,
learning_rate=0.1,
subsample=0.8,
colsample_bytree=0.8,
objective='multi:softprob',
num_class=6,
random_state=22
)
# 训练模型(传入样本权重)
model.fit(X_train, y_train, sample_weight=sample_weight)
print("模型训练完成")
return model
# 5. 评估模型
def evaluate_model(model, X_train, X_test, y_train, y_test):
"""评估模型"""
print("\n=== 评估模型 ===")
# 训练集评估
y_train_pred = model.predict(X_train)
train_acc = accuracy_score(y_train, y_train_pred)
print(f"训练集准确率: {train_acc:.4f}")
# 测试集评估
y_test_pred = model.predict(X_test)
test_acc = accuracy_score(y_test, y_test_pred)
print(f"测试集准确率: {test_acc:.4f}")
# 分类报告
print("\n分类报告:")
print(classification_report(y_test, y_test_pred))
return test_acc
# 6. 保存模型
def save_model(model, path='model/xgboost_wine_model.pkl'):
"""保存模型"""
print("\n=== 保存模型 ===")
import os
os.makedirs('model', exist_ok=True)
joblib.dump(model, path)
print(f"模型已保存到: {path}")
# 7. 主函数
def main():
"""主函数"""
print("=" * 50)
print("XGBoost - 红酒品质分类(模型训练)")
print("=" * 50)
# 1. 加载数据
train_data, test_data = load_data()
# 2. 提取特征和标签
X_train, X_test, y_train, y_test = extract_features_labels(train_data, test_data)
# 3. 平衡权重
sample_weight = balance_weights(y_train)
# 4. 创建和训练模型
model = train_model(X_train, y_train, sample_weight)
# 5. 评估模型
test_acc = evaluate_model(model, X_train, X_test, y_train, y_test)
# 6. 保存模型
save_model(model)
print("\n" + "=" * 50)
print("模型训练完成!")
print("=" * 50)
if __name__ == '__main__':
main()
输出示例:
==================================================
XGBoost - 红酒品质分类(模型训练)
==================================================
=== 加载数据 ===
训练集: (2615, 12)
测试集: (654, 12)
=== 提取特征和标签 ===
训练集特征: (2615, 11), 标签: (2615,)
测试集特征: (654, 11), 标签: (654,)
=== 平衡权重 ===
样本权重形状: (2615,)
样本权重范围: 0.1234 - 5.6789
类别0: 样本数=16, 平均权重=5.6789
类别1: 样本数=130, 平均权重=0.6987
类别2: 样本数=1238, 平均权重=0.0734
类别3: 样本数=1008, 平均权重=0.0902
类别4: 样本数=192, 平均权重=0.4731
类别5: 样本数=31, 平均权重=2.9301
=== 创建和训练模型 ===
模型训练完成
=== 评估模型 ===
训练集准确率: 0.8765
测试集准确率: 0.6544
分类报告:
precision recall f1-score support
0 0.00 0.00 0.00 4
1 0.25 0.06 0.10 33
2 0.67 0.75 0.71 309
3 0.64 0.69 0.66 252
4 0.33 0.15 0.21 48
5 0.00 0.00 0.00 8
accuracy 0.65 654
macro avg 0.32 0.28 0.28 654
weighted avg 0.61 0.65 0.62 654
=== 保存模型 ===
模型已保存到: model/xgboost_wine_model.pkl
==================================================
模型训练完成!
==================================================
5 重难点与易错提醒
- ❗重点:使用compute_sample_weight处理样本不均衡。
- ❗重点:class_weight='balanced'自动平衡权重。
- ❗重点:参考y_train的分布调整权重。
- ❗重点:训练时传入sample_weight参数。
- ⚠️易错:忘记平衡权重导致模型偏向多数类。
- ⚠️易错:导包方式导致前缀错误。
- 💡深入理解:样本少的类别权重高,样本多的类别权重低。
6 课堂问答精选
Q: 如何处理样本不均衡问题?
A: 使用compute_sample_weight函数:
from sklearn.utils.class_weight import compute_sample_weight
sample_weight = compute_sample_weight(class_weight='balanced', y=y_train)
然后在训练时传入:
model.fit(X_train, y_train, sample_weight=sample_weight)
样本少的类别权重高,样本多的类别权重低,使模型更关注少数类。
Q: 为什么导包方式影响使用方式?
A:
import xgboost as xgb:使用时需要xgb.XGBClassifier()from xgboost import XGBClassifier:使用时直接XGBClassifier()
类似于import math用math.log(),而from math import log用log()。
7 本课小结
- 数据加载:读取训练集和测试集。
- 特征提取:最后一列是标签,其他是特征。
- 平衡权重:compute_sample_weight(class_weight='balanced', y=y_train)。
- 模型训练:传入sample_weight参数。
- 模型保存:joblib.dump。
8 延伸思考与实践
- 实践:运行红酒品质分类训练代码。
- 预习:模型评测和网格搜索。
- 思考:为什么样本不均衡会影响模型效果?