高级数据科学家
概述
构建端到端数据科学工作流,涵盖从数据探索到模型部署的全过程。此技能涵盖数据预处理、特征工程、模型选择、超参数调优、交叉验证、使用 MLflow/W&B 跟踪实验、统计检验、使用 matplotlib/seaborn/plotly 进行可视化,以及 Jupyter notebook 最佳实践。
开始时声明:“我正在使用 senior-data-scientist 技能处理数据科学工作流。”
阶段 1:理解数据
**目标:**分析数据集并在建模前建立基准。
操作
- 加载并分析数据集(形状、类型、分布)
- 识别缺失值、异常值和数据质量问题
- 执行探索性数据分析(EDA)
- 定义目标变量和成功指标
- 建立基准性能
基准模型(始终从这里开始)
| 任务 | 基准模型 | 原因 |
|---|
| 分类 | 多数类分类器 | 准确率的下限 |
| 分类 | 逻辑回归 | 简单、易解释 |
| 回归 | 均值预测器 | RMSE 的下限 |
| 回归 | 线性回归 | 简单、易解释 |
| 时间序列 | 朴素预测(前一个值) | MAE 的下限 |
| 时间序列 | 季节性朴素预测 | 捕捉基本季节性 |
停止 — 在进入阶段 2 之前,不要继续:
阶段 2:特征工程
**目标:**将原始数据转换为可提升模型性能的特征。
操作
- 处理缺失值(填补策略)
- 对分类变量进行编码
- 缩放/归一化数值特征
- 创建派生特征
- 特征选择(移除冗余/无关特征)
缺失值策略决策表
| 策略 | 适用场景 | 实现方式 |
|---|
| 删除行 | 缺失率 < 5%,MCAR | df.dropna() |
| 均值/中位数 | 数值型、无异常值 | SimpleImputer(strategy='median') |
| 众数 | 分类变量 | SimpleImputer(strategy='most_frequent') |
| KNN 填补器 | 结构化缺失模式 | KNNImputer(n_neighbors=5) |
| 迭代填补 | 复杂关系 | IterativeImputer() |
| 标记 + 填补 | 缺失情况本身具有信息 | 添加 is_missing 列 + 填补 |
分类变量编码决策表
| 方法 | 适用场景 | 基数 |
|---|
| 独热编码 | 名义型、低基数 | < 10 个类别 |
| 标签/序数编码 | 序数特征 | 任意 |
| 目标编码 | 高基数名义型 | > 10 个类别 |
| 频率编码 | 频率具有意义时 | 任意 |
| 二进制编码 | 极高基数 | > 50 个类别 |
缩放决策表
| 缩放器 | 适用场景 | 对异常值稳健? |
|---|
| StandardScaler | 默认选择(均值=0,标准差=1) | 否 |
| RobustScaler | 存在异常值时(中位数/IQR) | 是 |
| MinMaxScaler | 神经网络、基于距离的方法 [0,1] | 否 |
特征类型与工程方法
| 特征类型 | 技术 |
|---|
| 数值型 | 对数变换、多项式、分箱、交互项(A*B、A/B) |
| 时间型 | 小时、星期几、is_weekend、距事件的时间、周期性(sin/cos)、滞后值 |
| 文本 | TF-IDF、词数、情感分数、命名实体、嵌入 |
| 分类 | 编码(见上文)、与数值特征交互 |
特征选择决策表
| 方法 | 类型 | 适用场景 |
|---|
| 相关性矩阵 | 过滤法 | 初步探索 |
| 互信息 | 过滤法 | 非线性关系 |
| 递归特征消除 | 包装法 | 特定模型的选择 |
| L1 正则化 | 嵌入法 | 线性模型 |
| 特征重要性 | 嵌入法 | 基于树的模型 |
| 置换重要性 | 与模型无关 | 最终验证 |
停止——在进入阶段 3 之前,请勿继续:
阶段 3:建模
目标: 选择、训练并评估候选模型。
操作
- 选择候选算法
- 设置交叉验证策略
- 训练并评估候选模型
- 调整超参数
- 最终模型选择与评估
算法决策表
| 数据特征 | 优先尝试 | 也可考虑 |
|---|
| 表格数据,行数 < 10K | Random Forest、XGBoost | Logistic/Linear Regression |
| 表格数据,行数 > 10K | XGBoost、LightGBM | CatBoost、Neural Network |
| 高维数据 | Lasso/Ridge、SVM | 配合特征选择的 Random Forest |
| 时间序列 | Prophet、ARIMA | LSTM、带滞后特征的 XGBoost |
| 文本分类 | 微调后的 transformer | TF-IDF + Logistic Regression |
| 图像分类 | 预训练 CNN(ResNet、EfficientNet) | Vision Transformer |
| 回归 | XGBoost、Random Forest | Linear Regression、Neural Network |
| 异常检测 | Isolation Forest | LOF、Autoencoder |
交叉验证策略决策表
| 策略 | 适用情况 | 代码 |
|---|
| K-Fold(k=5) | 默认选择,数据均衡 | KFold(n_splits=5) |
| Stratified K-Fold | 分类、数据不平衡 | StratifiedKFold(n_splits=5) |
| Time Series Split | 时间序列数据 | TimeSeriesSplit(n_splits=5) |
| Group K-Fold | 分组观测数据 | GroupKFold(n_splits=5) |
| Leave-One-Out | 数据集非常小 | LeaveOneOut() |
评估指标决策表
| 任务 | 主要指标 | 次要指标 |
|---|
| 二分类 | AUC-ROC | F1、Precision、Recall、AP |
| 多分类 | Macro F1 | Accuracy、Confusion Matrix |
| 回归 | RMSE | MAE、R-squared、MAPE |
| 排序 | NDCG | MAP、MRR |
| 异常检测 | F1、AP | Precision@K、Recall@K |
超参数调优决策表
| 方法 | 计算预算 | 搜索空间 | 实现方式 |
|---|
| Grid Search | 低(< 100 种组合) | 范围较小且已知 | GridSearchCV |
| Random Search | 中 | 范围大且不确定 | RandomizedSearchCV |
| Bayesian(Optuna) | 任意 | 范围大、计算开销高 | optuna.create_study() |
| Successive Halving | 高 | 候选项较多 | HalvingRandomSearchCV |
常见超参数(XGBoost/LightGBM)
param_space = {
'n_estimators': [100, 300, 500, 1000],
'max_depth': [3, 5, 7, 9],
'learning_rate': [0.01, 0.05, 0.1],
'subsample': [0.7, 0.8, 0.9],
'colsample_bytree': [0.7, 0.8, 0.9],
'min_child_weight': [1, 3, 5],
}
停止——在进入阶段 4 之前,请勿继续:
阶段 4:部署
目标: 序列化模型,在生产环境中提供服务并进行监控。
操作
- 序列化模型和预处理流程
- 创建预测 API 或批处理流程
- 设置数据漂移和模型性能下降监控
- 编写模型卡文档(输入、输出、局限性、偏差)
停止——满足以下条件时,部署完成:
实验跟踪
MLflow 模式
import mlflow
mlflow.set_experiment("customer-churn-prediction")
with mlflow.start_run(run_name="xgboost-v2"):
mlflow.log_params(params)
mlflow.log_metrics({"auc": auc_score, "f1": f1_score})
mlflow.log_artifact("confusion_matrix.png")
mlflow.sklearn.log_model(pipeline, "model")
mlflow.set_tag("version", "2.1")
跟踪内容
| 类别 | 内容 |
|---|
| 参数 | 所有超参数、随机种子 |
| 指标 | 训练集和验证集指标 |
| 数据 | 数据版本/哈希值、特征列表 |
| 工件 | 图表、报告、模型文件 |
| 元数据 | 训练时长、模型大小 |
统计检验决策表
| 问题 | 检验 | 假设条件 |
|---|
| 两组均值是否不同? | t 检验(独立样本) | 正态分布 |
| 两组数据(非正态)? | Mann-Whitney U 检验 | 无 |
| 配对测量? | 配对 t 检验 | 差值服从正态分布 |
| 3 组或更多组的均值? | ANOVA | 正态分布、方差相等 |
| 分类变量是否相关? | 卡方检验 | 期望频数 > 5 |
| 分布是否为正态分布? | Shapiro-Wilk 检验 | n < 5000 |
| 两个分布是否不同? | Kolmogorov-Smirnov 检验 | 连续数据 |
P 值指南
- p < 0.05:具有统计显著性(常用标准)
- 始终同时报告效应量和 p 值
- 对多重比较进行校正(Bonferroni、FDR)
- 统计显著性不等于实际显著性
可视化决策表
| 数据类型 | 图表 | 库 |
|---|
| 分布 | 直方图、KDE、箱线图 | seaborn |
| 比较 | 条形图、分组条形图 | matplotlib |
| 相关性 | 散点图、热力图 | seaborn |
| 趋势 | 折线图 | matplotlib/plotly |
| 构成 | 堆叠条形图、饼图(最多 5 个扇区) | matplotlib |
| 交互式 | 散点图、折线图、仪表板 | plotly |
可视化规则
- 为每张图表添加描述性标题
- 为坐标轴标注单位
- 使用适合色盲人士的调色板(
seaborn: colorblind)
- 条形图的 y 轴从 0 开始
- 直接在图表上标注关键发现
Jupyter Notebook 结构
1. ## Setup (imports, configuration)
2. ## Data Loading
3. ## Exploratory Data Analysis
4. ## Data Preprocessing
5. ## Feature Engineering
6. ## Modeling
7. ## Evaluation
8. ## Conclusions
Notebook 最佳实践
- 分享前重启内核并运行全部单元格
- 保持单元格内容聚焦、顺序清晰
- 使用 Markdown 单元格进行说明
- 将可复用代码提取到
.py 模块中
- 使用
nbstripout 进行版本控制
- 固定所有依赖项的版本
反模式 / 常见错误
| 反模式 | 错误原因 | 正确做法 |
|---|
| 使用测试数据进行训练 | 数据泄漏,指标虚高 | 严格区分训练集和测试集 |
| 在拆分数据前进行特征工程 | 测试集信息泄漏到特征中 | 仅使用训练数据进行特征工程 |
| 报告训练指标 | 无法泛化 | 报告验证集/测试集指标 |
| 在类别不平衡的数据上使用准确率 | 会产生误导(多数类占优) | 使用 F1、AUC-ROC 或 AP |
| 在测试集上调参 | 对测试数据过拟合 | 使用验证集调参 |
| 不与基线比较 | 无法衡量改进程度 | 始终先建立基线 |
| 挑选评估示例 | 存在选择偏差 | 在完整评估集上报告结果 |
| 部署时不监控漂移 | 模型性能悄然下降 | 监控输入分布 |
集成点
| 技能 | 关系 |
|---|
senior-prompt-engineer | 提示词评估会用到统计检验方法 |
testing-strategy | ML 测试遵循评估方法 |
performance-optimization | 模型推理优化遵循测量周期 |
acceptance-testing | 模型性能阈值成为验收标准 |
llm-as-judge | 主观输出评估使用 LLM-as-judge |
code-review | 对 Notebook 和流水线代码进行质量审查 |
技能类型
灵活型 — 根据具体的数据特征、业务需求和计算资源限制,调整预处理、建模和评估方法。强烈建议采用四阶段流程并跟踪实验。建模前务必先建立基线。