小白python入门 - 75. 综合实战
0. 写给初学:第一次「端到端」比刷榜更重要
66~74 课像散装零件:
- 会划分训练测试、会 Pipeline、会分类回归、会树与调参;
- 会一点聚类、会浅层文本、会把模型存起来开个
/predict。
本课任务:自己选一个题目,把零件装成一台能交出去的小机器。
什么叫「交得出去」?不是只截一张 0.99 准确率:
| 交付物 | 白话 |
|---|---|
| 可复现代码 | 别人按 README 能跑出同一量级的结果 |
| 指标表 + 图 | 说清楚在哪个集合、哪个协议下测的 |
| 错误/残差分析 | 知道模型蠢在哪 |
| 模型卡 | 用途、数据、局限写明白 |
| (可选)推理示例 | joblib 或最小 API |
你没有项目经验很正常。本课用清单 + 弱基线先行降低恐慌:
先做一个「笨但正确」的版本,再一点点变聪明。
1. 背景例子:三种选题,选一个做深
| 选题 | 任务 | 数据从哪来 | 适合练什么 |
|---|---|---|---|
| A. Titanic | 乘客是否生还(分类) | Kaggle 公开 | 缺失、类别特征、基线文化 |
| B. 房价 | 预测房价(回归) | sklearnfetch_california_housing或 Kaggle | 指标 RMSE/MAE、残差 |
| C. 业务二分类 | 流失 / 违约 / 复购… | 课程模拟表或实习脱敏表 | 口径、类别不平衡、业务解释 |
怎么选?
- 想跟全球教程对齐、资料多 →A;
- 想延续 69 课回归 →B;
- 想写进简历「业务问题」→C(注意隐私,别上传真实身份证号之类)。
一票否决:选题必须能在1~2 周业余时间跑完闭环。别一上来「推荐系统 + 多模态」。
2. 图解一:像 CRISP-DM 一样走路,而不是「先调参三天」
工业界有个老流程叫CRISP-DM(跨行业数据挖掘标准流程)。名字难记,步骤很朴素:
| 阶段 | 白话问题 | 你的输出 |
|---|---|---|
| 1. 业务理解 | 预测什么?成功长什么样?误判谁更惨? | 半页问题定义 |
| 2. 数据理解 | 有哪些表/字段?缺测?泄漏字段? | EDA 笔记 + 数据字典 |
| 3. 数据准备 | 清洗、特征、划分 | Pipeline 草稿 |
| 4. 建模 | 弱基线 → 真模型 → 调参 | 实验记录表 |
| 5. 评估 | 固定协议;测试集尽量只碰一次 | 指标 + 图 + 错误分析 |
| 6. 部署/交付 | 报告、模型卡、可选 API | 文件夹打包 |
和 66 课地图是同构的,只是本课要求你走完并留下痕迹。
Kaggle 文化提醒:公共排行榜可以当参考,但对着榜狂刷到过拟合榜单是经典翻车。课程作业以你自己的验证协议为准。
3. 图解二:弱基线先行——先当「笨学生」
很多人一上来就:
随机森林 + 网格搜索 200 组 + 特征魔法然后不知道提升来自数据运气还是真本事。
正确顺序:
① 规则/多数类/均值基线 ← 几乎零机器学习 ② 简单模型(逻辑回归/线性) ← 可解释、好查泄漏 ③ 树 / 森林等 ← 挖非线性 ④ 有限调参 + 同一 CV ← 71 课纪律 ⑤ 测试集最终一次报告 ← 诚实分数| 基线类型 | 分类例子 | 回归例子 |
|---|---|---|
| 极弱 | 永远猜多数类 | 永远猜训练集均值 |
| 简单 ML | 逻辑回归 + 基本预处理 | 岭回归 |
| 进阶 ML | 随机森林 / GBDT 直觉 | 随机森林回归 |
只有超过极弱基线,你的模型才「值回票价」。
若森林不赢逻辑回归,先查特征与泄漏,而不是继续加层数。
4. 推荐目录结构(交作业像交工程项目)
my_ml_project/ README.md # 怎么跑、结论三句话 requirements.txt data/ raw/ # 只读原始数据(可 gitignore 大文件) processed/ # 可选中间表 notebooks/ 01_eda.ipynb 02_model.ipynb src/ # 可选:把 Pipeline 函数放这里 data.py features.py train.py models/ pipe.joblib reports/ metrics.md figures/ MODEL_CARD.md初学可以全用 Notebook,但至少:
- 固定
random_state; - 写清数据路径;
- 最终指标复制到
reports/metrics.md。
5. 问题定义模板(先写这个再写代码)
复制到你的README开头:
## 问题定义 - 任务类型:分类 / 回归 - 预测目标 y: - 正类含义(若分类): - 成功指标:例如 test F1 ≥ ? 或 RMSE ≤ ? - 误判代价:假阳 / 假阴哪个更贵? - 数据范围:时间、样本是否 iid? - 明确不用的字段(泄漏):例如「事后才知道的列」泄漏字段举例(Titanic 思想):
若某字段是「获救后才填写的备注」,训练时用了等于作弊。业务里「是否已流失」相关的事后标签列同理。
6. 代码骨架:弱基线 → Pipeline → CV → 测试集
下面以分类示意(回归把指标换成 RMSE/MAE 即可)。
数据请换成你的选题。
frompathlibimportPathimportjsonimportjoblibimportnumpyasnpimportpandasaspdfromsklearn.model_selectionimporttrain_test_split,cross_val_score,StratifiedKFoldfromsklearn.composeimportColumnTransformerfromsklearn.pipelineimportPipelinefromsklearn.imputeimportSimpleImputerfromsklearn.preprocessingimportOneHotEncoder,StandardScalerfromsklearn.linear_modelimportLogisticRegressionfromsklearn.ensembleimportRandomForestClassifierfromsklearn.metricsimport(accuracy_score,f1_score,classification_report,confusion_matrix)fromsklearn.dummyimportDummyClassifier RANDOM_STATE=42DATA_PATH=Path("data/raw/train.csv")# 按你的路径改df=pd.read_csv(DATA_PATH)# 示例列名:请改成真实列TARGET="Survived"y=df[TARGET]X=df.drop(columns=[TARGET])# 1) 先划出「终极考场」——之后尽量少看X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=RANDOM_STATE,stratify=y)6.1 极弱基线
dummy=DummyClassifier(strategy="most_frequent")dummy.fit(X_train,y_train)pred_dummy=dummy.predict(X_test)print("dummy acc",accuracy_score(y_test,pred_dummy))print("dummy f1 ",f1_score(y_test,pred_dummy,zero_division=0))把数字记进实验表:这是你的地板。
6.2 列类型与预处理(防泄漏:进 Pipeline)
num_cols=X_train.select_dtypes(include=["number"]).columns.tolist()cat_cols=[cforcinX_train.columnsifcnotinnum_cols]numeric=Pipeline([("imputer",SimpleImputer(strategy="median")),("scaler",StandardScaler()),])categorical=Pipeline([("imputer",SimpleImputer(strategy="most_frequent")),("onehot",OneHotEncoder(handle_unknown="ignore")),])pre=ColumnTransformer([("num",numeric,num_cols),("cat",categorical,cat_cols),])6.3 模型字典 + 同一交叉验证协议
models={"log_reg":LogisticRegression(max_iter=2000),"rf":RandomForestClassifier(n_estimators=200,random_state=RANDOM_STATE,n_jobs=-1),}cv=StratifiedKFold(n_splits=5,shuffle=True,random_state=RANDOM_STATE)rows=[]best_name,best_score,best_pipe=None,-np.inf,Noneforname,clfinmodels.items():pipe=Pipeline([("pre",pre),("clf",clf)])scores=cross_val_score(pipe,X_train,y_train,cv=cv,scoring="f1")rows.append({"model":name,"cv_f1_mean":scores.mean(),"cv_f1_std":scores.std()})print(name,scores.mean(),scores.std())ifscores.mean()>best_score:best_name,best_score=name,scores.mean()best_pipe=pipeprint(pd.DataFrame(rows))6.4 仅在选定模型上 fit 全训练集,再测一次 test
best_pipe.fit(X_train,y_train)pred=best_pipe.predict(X_test)print("TEST",best_name)print(classification_report(y_test,pred,digits=3))print(confusion_matrix(y_test,pred))Path("models").mkdir(exist_ok=True)joblib.dump({"pipeline":best_pipe,"model_name":best_name,"features":list(X_train.columns),"model_version":"1.0.0",},"models/pipe.joblib",)纪律:
- 调参、选模型主要看CV 或验证集;
- test 是最终报告,不是调参旋钮;
- 若 test 远差于 CV,可能过拟合或划分不稳——回去查,而不是偷偷重划 test 到满意为止。
7. 回归选题差异(房价等)
| 项 | 分类 | 回归 |
|---|---|---|
| 弱基线 | DummyClassifier | DummyRegressor(strategy="mean") |
| 常用指标 | F1 / ROC-AUC / 召回 | MAE / RMSE / R² |
| 错误分析 | 混淆矩阵、错分样本 | 残差图、最大误差样本 |
| 分层划分 | stratify=y | 可按 y 分箱后再分层(进阶) |
fromsklearn.dummyimportDummyRegressorfromsklearn.metricsimportmean_absolute_error,mean_squared_error,r2_score# pred = pipe.predict(X_test)# print("MAE", mean_absolute_error(y_test, pred))# print("RMSE", mean_squared_error(y_test, pred) ** 0.5)# print("R2", r2_score(y_test, pred))8. 实验记录表(防止「我昨天那个好像 0.84」)
建议reports/experiments.csv或 Markdown 表:
| run_id | 日期 | 模型 | 关键改动 | CV 指标 | test 指标 | 备注 |
|---|---|---|---|---|---|---|
| 001 | 07-20 | dummy | 多数类 | - | acc=0.62 | 地板 |
| 002 | 07-20 | log_reg | 中位数+onehot | f1=0.71 | - | |
| 003 | 07-21 | rf | n_estimators=200 | f1=0.76 | f1=0.74 | 入选 |
改动一次记一行。这是科研/工业都认的基本功。
9. 错误分析清单(有分还要有故事)
分类:
- 打印 10 条假阳性、10 条假阴性;
- 看是否某类别特征主导误判;
- 阈值要不要从 0.5 调(代价不对称时)。
回归:
- 残差 = 预测 - 真值,画直方图;
- 最大误差的 10 个样本有何共同特征;
- 是否需要对数变换目标(房价长尾)。
把结论写进报告:
模型容易在「年龄缺失 + 低票价」乘客上判错…… 建议:业务上对此类样本人工复核 / 增加特征……10. 模型卡:把 74 课模板填满
reports/MODEL_CARD.md至少包含:
- 任务与算法;
- 数据来源与划分;
- 指标(写明 test / CV);
- 预期用途与不适用场景;
- 局限(偏差、泄漏风险、未做公平性评估等);
- 复现方式(命令、随机种子、依赖版本)。
诚实写「未评估」比吹「AI 赋能百分之百」加分。
11. 可选加分项
| 加分 | 说明 |
|---|---|
| 学习曲线 | 71 课:数据量是否还够 |
| 排列重要性 / 系数 | 解释 top 特征 |
FastAPI/predict | 74 课最小服务 |
| 文本字段 | 73 课浅层(若业务有备注文本) |
| 简单阈值或代价矩阵 | 业务导向,不只 accuracy |
加分项可选。主线闭环没完成前不要炫技。
12. 端到端检查清单(交之前逐项打勾)
问题与数据
- 问题定义半页写清
- 数据字典(每列含义)
- 已识别并排除泄漏字段
- 划分方式与
random_state固定
训练纪律
- 有极弱基线数字
- ≥2~3 类模型同一协议对比
- 预处理在 Pipeline 内,无「先全表 fit」
- 调参未污染最终 test(或诚实说明协议)
评估与报告
- 指标表 + 至少 1 张图(混淆矩阵 / 残差 / 对比条形图)
- 错误分析 ≥5 条样本或等价分析
- 三句话业务结论(不是只报分)
交付物
- README 可复现步骤
requirements.txtMODEL_CARD.md- (可选)
models/pipe.joblib与预测示例
13. 报告「三句话结论」范例
差的结论:
我用了随机森林,准确率很高。
好的结论:
- 在 5 折 CV 上随机森林 F1=0.76,高于逻辑回归 0.71 与多数类基线 0.48。
- 测试集 F1=0.74;主要假阴性集中在年龄缺失样本。
- 建议上线前对缺失年龄客群人工复核;当前模型仅作辅助排序,不作唯一决策。
14. 常见坑
| 坑 | 正确直觉 |
|---|---|
| 无基线直接调参 | 先地板,再谈提升 |
| 测试集当验证集反复用 | 分数虚高;固定协议 |
| 全数据 fit 预处理器 | 泄漏;用 Pipeline |
| 只交 Notebook 无说明 | 别人(和未来的你)跑不起来 |
| 指标与业务脱节 | 不平衡时别只报 accuracy |
| 榜单分数当唯一目标 | 可解释与稳定更重要 |
| 用生成式 AI 写代码但不懂 | 可以辅助,评测与泄漏纪律不能外包 |
| 项目过大烂尾 | 缩小范围,完成闭环优先 |
15. 小结
- 综合实战 =问题定义 → 数据 → 弱基线 → 模型对比 → 诚实评估 → 文档交付。
- 流程与CRISP-DM同构,按清单走即可。
- 弱基线先行,同一协议下对比 ≥2~3 类算法。
- Pipeline 防泄漏;test 少碰;留下实验表。
- 交付看可复现 + 模型卡 + 错误分析,不是只看最高分。
- 本阶段(66~75)收官:表格 ML 主线 + 文本浅层 + 服务化意识;深度学习与大模型训练留给后续专项。
16. 练笔(本课主作业)
必做:
- 三选一选题(Titanic / 房价 / 业务二分类),完成第 12 节检查清单。
- 实验表 ≥3 行(含 dummy 或等价弱基线)。
reports/MODEL_CARD.md填满。- README 含环境、命令、三句话结论。
选做:
- 导出 joblib,离线
predict3 条新样本。 - 最小 FastAPI
/predict。 - 增加一张「模型对比」图(可用 matplotlib 条形图)。
时间盒建议:EDA 30% · 基线与模型 40% · 报告文档 30%。宁可模型简单,也不要文档空。
17. 引用与参考
| 引用了 | 用途 | 链接 |
|---|---|---|
| Wikipedia: CRISP-DM | 端到端流程参照 | https://en.wikipedia.org/wiki/Cross-industry_standard_process_for_data_mining |
| Kaggle Titanic | 入门竞赛与数据 | https://www.kaggle.com/competitions/titanic |
| scikit-learn User Guide | API 总览 | https://scikit-learn.org/stable/user_guide.html |
| scikit-learn Common pitfalls | 泄漏与预处理 | https://scikit-learn.org/stable/common_pitfalls.html |
| scikit-learn Cross-validation | 固定评估协议 | https://scikit-learn.org/stable/modules/cross_validation.html |
| scikit-learn Metrics | 分类/回归指标 | https://scikit-learn.org/stable/modules/model_evaluation.html |
| scikit-learn Model persistence | 模型导出 | https://scikit-learn.org/stable/model_persistence.html |
| Mitchell et al. Model Cards (2019) | 模型卡 | https://arxiv.org/abs/1810.03993 |
| ISLR 官网 | 统计学习概念加餐 | https://www.statlearning.com/ |
| sklearn California housing | 回归练习数据 | https://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_california_housing.html |
18. 与前后课
| 方向 | 内容 |
|---|---|
| 前 | 66~74 全部收口:地图、预处理、分类回归、树、调参、聚类扫盲、文本、服务化 |
| 本课 | 选题、弱基线、对比、报告、模型卡、可选部署 |
| 后 | 竞赛深挖、MLOps、深度学习/大模型专项、业务实习项目 |
19. 阶段结束时你应该具备的能力(自检)
- 能判断问题是分类还是回归,并选对指标
- 会用 Pipeline 做预处理且避免泄漏
- 会对比多种算法并做有限调参
- 知道词袋/TF-IDF 浅层文本怎么上手
- 会保存模型并理解服务化与模型卡
- 能独立完成一个可复现的小项目文件夹
若以上大多能勾选:恭喜,你已经不是「只听过 AI」的初学,而是能把监督学习跑通闭环的新手。接下来缺的是更多真实数据上的伤疤——那只能靠项目,不靠再看十篇导论。
课堂讨论题(可分组 10 分钟)
- 如果老板只要一个数字「准确率」,你怎么用两分钟说服他看混淆矩阵?
- 数据只有 80 条,你还上机器学习吗?为什么?
- 你更愿意维护:100 条清晰业务规则,还是一个 90 分但没人能解释的模型?
把讨论结论写在笔记里——比多抄 50 行 API 更接近真实工作。
自我检测(不看稿,口头答)
- 我能不看笔记讲清本课最重要的一张图在说什么
- 我能指出一段「错误代码」错在哪
- 我能举一个生活例子对应本课任务类型
- 我知道下一课大概要解决什么痛点
全部打勾再进入下一课,效率更高。
附录:给初学的 FAQ(本课补充)
下面这些问题,是第一次学本课内容时最容易卡住的地方。用白话再过一遍。
Q1:我是不是一定要背公式?
不必先背公式。你要先会讲故事:输入是什么、输出是什么、模型在怕什么(过拟合、泄漏、指标骗人)。公式是为了精确表达故事;故事通了,公式只是翻译。
Q2:代码跑不通怎么办?
按这个顺序排查:
- 虚拟环境激活了吗?(提示符前有没有 .venv)
- 包装了吗?python -c “import sklearn; print(sklearn.version)”
- 报错最后一行是什么?把Error 类型 + 最后一行记下来再搜
- 路径、文件名、中文引号有没有混用
- 仍不行:换一个最小例子(本课最前面的 10 行代码)确认环境 OK
Q3:我和同学分数差很多,是不是我很差?
不一定。可能是:
andom_state 不同、数据划分不同、指标不同、甚至泄漏导致虚高。先对齐评估协议,再比分数。
Q4:这课和「人工智能 / ChatGPT」是什么关系?
ChatGPT 一类是很大的深度学习系统,偏语言与对话。本课练的是表格/经典机器学习基本功:分类、回归、评估、Pipeline。基本功会了,你以后学深度学习或用大模型 API,才知道自己在解决什么问题、如何公平比较。
Q5:我需要买 GPU 吗?
本阶段不需要。sklearn 在普通笔记本 CPU 上就够。GPU 主要是深度学习训练时才刚需。
Q6:作业要做到什么程度算合格?
最低标准:
- 能用自己的话讲清本课 3 个核心概念
- 能跑通本课主线代码,并看懂输出含义
- 能指出至少 2 个常见坑
- 小练笔完成一半以上(鼓励全做)
Q7:我想继续深入,课外看什么?
优先官方文档对应章节(见文末引用),其次 ISLR 中文/英文入门章节。别一上来就啃很厚的证明书——容易劝退。
本课概念速记卡(可抄笔记本)
| 我用大白话怎么说 | 对应术语 |
|---|---|
| 用历史数据猜新情况 | 机器学习 / 预测 |
| 拿来学的那部分数据 | 训练集 |
| 假装是新客户的那部分 | 测试集 |
| 背答案背过头 | 过拟合 |
| 笨到学不会 | 欠拟合 |
| 偷看了考题 | 数据泄漏 |
| 步骤焊成一条龙 | Pipeline |
建议学习节奏
| 时间 | 做什么 |
|---|---|
| 第 1 小时 | 只读例子与图,不写代码 |
| 第 2 小时 | 抄跑主线代码,改一个参数观察变化 |
| 第 3 小时 | 做小练笔 + 写 5 句笔记 |
| 之后 | 隔一天不看稿子复述一遍 |
记住:初学阶段,「讲清楚 + 跑得通 + 知道坑」比「一次记住全部 API」重要得多。