ML 项目最佳实践
📌 核心定义 (What)
Section titled “📌 核心定义 (What)”一句话定义:ML 项目不只是训练模型,而是从问题定义到生产部署的完整流程。80% 的时间花在数据上,只有 20% 在模型上。
🚀 ML 项目生命周期
Section titled “🚀 ML 项目生命周期”-
问题定义 & 数据收集
- 明确业务目标和成功指标
- 收集、标注数据
- 评估数据质量和数量
-
数据探索 & 预处理
- EDA (探索性数据分析)
- 处理缺失值、异常值
- 特征工程
-
数据集划分
- Train / Validation / Test 划分
- 避免数据泄露
-
模型选择 & 训练
- 基线模型 → 复杂模型
- 交叉验证
- 超参数调优
-
误差分析 & 迭代
- 分析错误案例
- 偏差/方差诊断
- 迭代改进
-
部署 & 监控
- 模型服务化
- A/B 测试
- 持续监控
📊 数据集划分 (最重要!)
Section titled “📊 数据集划分 (最重要!)”标准划分比例
Section titled “标准划分比例”| 数据量 | Train | Validation | Test |
|---|---|---|---|
| < 10,000 | 60% | 20% | 20% |
| 10,000 - 1M | 80% | 10% | 10% |
| > 1M | 98% | 1% | 1% |
from sklearn.model_selection import train_test_split
# 正确做法:先分出 Test,再从剩余数据分 Train/ValX_temp, X_test, y_temp, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y # 分层采样)X_train, X_val, y_train, y_val = train_test_split( X_temp, y_temp, test_size=0.25, random_state=42, stratify=y_temp)# 最终比例: 60% train, 20% val, 20% test⚠️ 数据泄露 (Data Leakage)
Section titled “⚠️ 数据泄露 (Data Leakage)”定义:训练时使用了测试集的信息,导致评估结果虚高。
| 常见泄露 | 正确做法 |
|---|---|
| 先标准化再划分 | 先划分,用 Train 的统计量标准化 Val/Test |
| 时序数据随机划分 | 按时间顺序划分,用过去预测未来 |
| 特征包含目标信息 | 检查特征与目标的相关性 |
# ❌ 错误:先标准化再划分from sklearn.preprocessing import StandardScalerscaler = StandardScaler()X_scaled = scaler.fit_transform(X) # 用了全部数据的统计量!X_train, X_test = train_test_split(X_scaled, ...)
# ✅ 正确:先划分再标准化X_train, X_test = train_test_split(X, ...)scaler = StandardScaler()X_train_scaled = scaler.fit_transform(X_train) # 只用 Train 的统计量X_test_scaled = scaler.transform(X_test) # 用同样的 scaler🎯 偏差-方差诊断
Section titled “🎯 偏差-方差诊断”| 情况 | Train Error | Val Error | 诊断 | 解决方案 |
|---|---|---|---|---|
| 高偏差 | 高 | 高 | 欠拟合 | 更复杂模型、更多特征、减少正则化 |
| 高方差 | 低 | 高 | 过拟合 | 更多数据、正则化、简化模型、Dropout |
| 理想 | 低 | 低 | ✅ | - |
from sklearn.model_selection import learning_curveimport matplotlib.pyplot as plt
train_sizes, train_scores, val_scores = learning_curve( model, X_train, y_train, cv=5, train_sizes=np.linspace(0.1, 1.0, 10))
plt.plot(train_sizes, train_scores.mean(axis=1), label='Train')plt.plot(train_sizes, val_scores.mean(axis=1), label='Validation')plt.xlabel('Training Size')plt.ylabel('Score')plt.legend()- 高偏差:两条线都低且接近
- 高方差:Train 高,Val 低,差距大
🔍 误差分析
Section titled “🔍 误差分析”- 收集错误样本:找出模型预测错误的案例
- 分类错误类型:手动标注错误原因
- 计算各类型占比:确定优先解决哪类问题
- 针对性改进:数据增强、特征工程、模型调整
示例:图像分类错误分析
Section titled “示例:图像分类错误分析”| 错误类型 | 占比 | 解决方案 |
|---|---|---|
| 模糊图像 | 40% | 数据增强(模糊处理) |
| 背景干扰 | 30% | 增加背景多样性 |
| 标注错误 | 20% | 清洗标注 |
| 其他 | 10% | - |
优先解决占比最高的问题!
📈 模型选择策略
Section titled “📈 模型选择策略”从简单到复杂
Section titled “从简单到复杂”-
基线模型
- 分类:逻辑回归、决策树
- 回归:线性回归
- 建立性能下限
-
中等复杂度
- Random Forest、XGBoost
- 调参验证
-
复杂模型
- 神经网络、深度学习
- 需要更多数据和计算资源
-
集成/融合
- 多模型投票/平均
- 比赛常用
不同场景的模型选择
Section titled “不同场景的模型选择”| 场景 | 推荐模型 | 原因 |
|---|---|---|
| 表格数据 < 10K | XGBoost/LightGBM | 效果好,训练快 |
| 表格数据 > 10K | 深度学习可考虑 | 数据量足够 |
| 图像 | CNN / ViT | 专门架构 |
| 文本 | Transformer | 预训练模型 |
| 时序 | LSTM / Transformer | 序列建模 |
🛠️ 代码组织结构
Section titled “🛠️ 代码组织结构”ml-project/├── data/│ ├── raw/ # 原始数据│ ├── processed/ # 处理后的数据│ └── external/ # 外部数据├── notebooks/│ ├── 01_eda.ipynb # 探索性分析│ ├── 02_baseline.ipynb # 基线模型│ └── 03_experiments.ipynb├── src/│ ├── data/ # 数据处理│ ├── features/ # 特征工程│ ├── models/ # 模型定义│ └── utils/ # 工具函数├── models/ # 保存的模型├── configs/ # 配置文件├── requirements.txt└── README.md✅ Checklist
Section titled “✅ Checklist”- 数据质量检查(缺失值、异常值、重复值)
- 数据集划分(无数据泄露)
- 类别不平衡处理
- 基线模型建立
- 交叉验证
- 超参数调优
- 学习曲线分析
- Test Set 只在最后使用一次
- 误差分析
- 模型保存与版本管理
- 监控指标定义