1. 项目概述
今天想和大家分享一个数据科学领域的经典实战项目——基于UCI数据集的多模型分类对比及特征选择实践。这个项目看似简单,但涵盖了机器学习从数据预处理到模型优化的完整流程,特别适合想要系统掌握分类任务全流程的朋友。
UCI机器学习仓库作为业内公认的标准数据集来源,包含了大量经过清洗和标注的真实数据。我们这次选择的是UCI中一个经典的分类数据集(具体可根据实际需求选择,比如鸢尾花、葡萄酒质量等数据集),通过对比随机森林、SVM等不同分类器的表现,同时结合特征选择技术来优化模型性能。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据准备与预处理
2.1 UCI数据集获取与探索
首先需要从UCI官网下载目标数据集。以经典的"Wine Quality"数据集为例,这个数据集包含了红酒的11个理化特征和对应的质量评分(3-9分)。我们可以将质量分为"好酒"(≥6分)和"普通酒"(<6分)两类,转化为二分类问题。
python复制import pandas as pd
from sklearn.model_selection import train_test_split
# 读取数据
data = pd.read_csv('winequality-red.csv', sep=';')
# 数据探索
print(data.head())
print(data.describe())
print(data.isnull().sum()) # 检查缺失值
2.2 数据清洗与特征工程
数据清洗是保证模型效果的基础步骤。我们需要:
- 处理缺失值:UCI数据集通常比较干净,但还是要检查
- 特征缩放:特别是对SVM这类对尺度敏感的模型
- 类别平衡:检查目标变量分布是否均衡
python复制from sklearn.preprocessing import StandardScaler
from sklearn.utils import resample
# 处理不平衡数据(如果需要)
df_majority = data[data.quality==0]
df_minority = data[data.quality==1]
df_minority_upsampled = resample(df_minority,
replace=True,
n_samples=len(df_majority),
random_state=42)
data = pd.concat([df_majority, df_minority_upsampled])
# 特征缩放
scaler = StandardScaler()
features = data.drop('quality', axis=1)
scaled_features = scaler.fit_transform(features)
3. 多模型分类实现
3.1 基础模型构建
我们选择四种典型的分类算法进行对比:
- 随机森林(Random Forest)
- 支持向量机(SVM)
- 逻辑回归(Logistic Regression)
- 梯度提升树(XGBoost)
python复制from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from xgboost import XGBClassifier
from sklearn.model_selection import cross_val_score
# 初始化模型
models = {
'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42),
'SVM': SVC(kernel='rbf', C=1.0, gamma='scale'),
'Logistic Regression': LogisticRegression(max_iter=1000),
'XGBoost': XGBClassifier(use_label_encoder=False, eval_metric='logloss')
}
# 交叉验证评估
for name, model in models.items():
scores = cross_val_score(model, scaled_features, data['quality'], cv=5)
print(f"{name}平均准确率: {scores.mean():.4f} (±{scores.std():.4f})")
3.2 模型参数调优
以随机森林为例,演示如何进行网格搜索调参:
python复制from sklearn.model_selection import GridSearchCV
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [None, 10, 20],
'min_samples_split': [2, 5, 10]
}
rf = RandomForestClassifier(random_state=42)
grid_search = GridSearchCV(estimator=rf, param_grid=param_grid, cv=5)
grid_search.fit(X_train, y_train)
print("最佳参数:", grid_search.best_params_)
print("最佳得分:", grid_search.best_score_)
4. 特征选择技术应用
4.1 基于模型的特征重要性
随机森林本身可以提供特征重要性评估:
python复制# 训练最佳随机森林模型
best_rf = RandomForestClassifier(**grid_search.best_params_, random_state=42)
best_rf.fit(X_train, y_train)
# 获取特征重要性
importances = best_rf.feature_importances_
features = X_train.columns
feature_importance = pd.DataFrame({'feature':features, 'importance':importances})
feature_importance = feature_importance.sort_values('importance', ascending=False)
# 可视化
import matplotlib.pyplot as plt
plt.figure(figsize=(10,6))
plt.barh(feature_importance['feature'], feature_importance['importance'])
plt.xlabel('Importance')
plt.title('Feature Importance from Random Forest')
plt.show()
4.2 SHAP值分析
SHAP是一种更先进的特征重要性解释方法:
python复制import shap
# 创建SHAP解释器
explainer = shap.TreeExplainer(best_rf)
shap_values = explainer.shap_values(X_test)
# 可视化
shap.summary_plot(shap_values, X_test, plot_type="bar")
shap.summary_plot(shap_values[1], X_test) # 对正类的SHAP值
4.3 递归特征消除(RFE)
另一种系统性的特征选择方法:
python复制from sklearn.feature_selection import RFE
# 使用逻辑回归作为基础模型
selector = RFE(LogisticRegression(max_iter=1000), n_features_to_select=5)
selector = selector.fit(X_train, y_train)
# 查看被选中的特征
selected_features = X_train.columns[selector.support_]
print("Selected features:", list(selected_features))
5. 模型性能对比与选择
5.1 评估指标对比
除了准确率,我们还需要关注其他指标:
python复制from sklearn.metrics import classification_report, roc_auc_score
# 在测试集上评估最佳模型
y_pred = best_rf.predict(X_test)
y_proba = best_rf.predict_proba(X_test)[:,1]
print(classification_report(y_test, y_pred))
print("ROC AUC:", roc_auc_score(y_test, y_proba))
5.2 学习曲线分析
检查模型是否过拟合或欠拟合:
python复制from sklearn.model_selection import learning_curve
import numpy as np
train_sizes, train_scores, test_scores = learning_curve(
best_rf, X_train, y_train, cv=5,
train_sizes=np.linspace(0.1, 1.0, 5),
scoring='accuracy')
plt.figure(figsize=(10,6))
plt.plot(train_sizes, np.mean(train_scores, axis=1), label='Training score')
plt.plot(train_sizes, np.mean(test_scores, axis=1), label='Cross-validation score')
plt.xlabel('Training examples')
plt.ylabel('Accuracy')
plt.legend()
plt.title('Learning Curve')
plt.show()
6. 实战经验与注意事项
6.1 特征选择中的常见陷阱
- 数据泄露问题:特征选择应该在交叉验证的每个fold内独立进行,而不是在整个数据集上做
- 特征重要性解释:高重要性不一定代表因果关系
- 多共线性问题:相关特征可能分散重要性分数
6.2 模型选择建议
- 对于结构化数据,树模型(随机森林、XGBoost)通常是首选
- SVM在小数据集上表现良好,但对参数敏感且不易解释
- 逻辑回归简单快速,适合作为基准模型
6.3 性能优化技巧
- 对于随机森林,
n_estimators可以设置较大值(200+),因为增加树的数量不会导致过拟合 - XGBoost的
learning_rate通常设置在0.01-0.3之间,配合更大的n_estimators - 使用早停法(early stopping)可以防止过拟合并节省训练时间
7. 项目扩展方向
这个基础项目可以进一步扩展:
- 尝试更多特征选择方法:如互信息、卡方检验等
- 实现自动化机器学习(AutoML)流程
- 将最佳模型部署为Web服务
- 探索深度学习方法在相同数据集上的表现
提示:在实际项目中,建议使用MLflow或Weights & Biases等工具记录实验过程,方便比较不同模型和参数组合的效果。
