本文收录于专栏 《经典机器学习实战》
摘要:菜系分类第一课:亚洲五菜系数据又脏又不平衡,删掉无判别力的通用食材、SMOTE 过采样把 2448 行变成五类各 799 行。这份数据将贯穿后面三课,从分类器横评一直到 ONNX 部署。
关键字:SMOTE,类别不平衡,数据清洗,独热编码,多分类,菜系数据集,过采样,特征选择
阶段 3 · 分类(菜系项目)| 来源:【原·10】| 知识更新至 2026-10
概念讲解
6.1 从二分类到多分类
第 4 课的逻辑回归做的是二分类(橙色/白色)。分类任务的另一半世界是多分类(multiclass classification) :标签不止两个。本阶段的问题是------给一袋食材,判断它属于哪个国家的菜系。
数据是亚洲与印度菜系数据集:2448 道菜、5 个菜系(korean / indian / chinese / japanese / thai)、380+ 种食材,每道菜在每个食材上标记 0 或 1(用没用)。换成第 3 课的词汇:X 是 380 维 0-1 向量,y 是 5 选 1 的菜系标签。
6.2 建模前先看分布:不平衡是毒药
拿到分类数据的第一件事是看类别分布:
korean 799
indian 598
chinese 442
japanese 320
thai 289
最多(korean 799)是最少(thai 289)的 2.8 倍。这有什么问题?回忆第 3 课的实测:多数类会吸走模型的全部注意力------模型只要"偏向猜 korean",就能白拿一部分准确率,而 thai 会被系统性牺牲。第 4 课的白色南瓜(recall 0.67)已经演示过一次。
6.3 SMOTE:合成少数类样本
修复不平衡的办法之一:SMOTE(Synthetic Minority Over-sampling Technique,合成少数类过采样技术) 。它不是简单复制少数类样本,而是在特征空间里,取少数类样本与其近邻之间插值生成新样本------新样本"像"少数类但不重复,比硬复制更不容易过拟合。
工具是 imblearn 库(scikit-learn 的姊妹包,API 同构):
python
from imblearn.over_sampling import SMOTE
oversample = SMOTE(random_state=42)
X_balanced, y_balanced = oversample.fit_resample(feature_df, labels_df)
fit_resample 返回平衡后的特征与标签:每个菜系都被"补"到与最多类相同的 799 条。
6.4 降噪:删掉"人人都用"的食材
平衡之前还有一步特征层面的清洗。看各菜系 top 10 食材(以 thai 为例):
garlic 173, fish 153, cayenne 136, cilantro 121, ginger 114,
coconut 111, vegetable_oil 106, coriander 105, rice 102, chicken 97
注意 garlic(蒜)、ginger(姜)、rice(米)------这三个在所有亚洲菜系里都高频。所有菜系都用的食材没有区分度,留着只会增加类间混淆。直接删:
python
feature_df = df.drop(['cuisine', 'Unnamed: 0', 'rice', 'garlic', 'ginger'], axis=1)
特征从 383 减到 380。删特征听起来损失信息,实际相反:把"噪声特征"去掉,剩下的特征每个都更有区分责任------这是特征选择(第 3 课概念)的实战。
案例实战:从脏数据到平衡数据
实测环境:conda env
ml-course(pandas 3.0.6 / imbalanced-learn 0.14.2),2026-10-05 运行完整脚本:
stage3/assets/stage3_demos.py
目标:跑完"体检 → 删降噪食材 → SMOTE 平衡 → 存盘"全流程。
第 1 步:体检
shape = (2448, 385) # 2448 道菜 × (1 索引 + 1 标签 + 383 食材)

左图:5 个菜系分布明显不均(korean 接近 thai 的三倍)。右图:thai 的 top10 食材,garlic/ginger/rice 果然在列------全亚洲通用,删。
第 2 步:SMOTE 平衡
SMOTE 后行数 = 3995
indian 799 / thai 799 / chinese 799 / japanese 799 / korean 799
2448 → 3995 行,5 个菜系完全均衡。SMOTE 为 thai 合成了 510 条新样本、为 japanese 合成 479 条,以此类推。
第 3 步:存盘
平衡后的数据保存为 cleaned_cuisines.csv,后续三课(11/12/13)全部用它。固定 random_state=42 保证每次生成的合成样本一致、数字可复现。
SMOTE 前后数据对比(实测):
| 平衡前 | 平衡后 | |
|---|---|---|
| 总行数 | 2448 | 3995 |
| 每类样本 | 不均(最少 1xx) | 799 × 5 类 |
| 删掉的食材 | --- | rice/garlic/ginger(全菜系通用,无判别力) |
| 教学点 | 多数类淹没少数类 | 少数类合成过采样 |
小结
- 多分类 = 标签多于两个的分类任务;菜系数据集 2448 道 × 380 食材特征 × 5 菜系。
- 类别不平衡会让多数类"白捡"准确率、牺牲少数类------建模前先看分布。
- SMOTE 用插值合成少数类新样本(不是复制),本课把 2448 行补成 3995 行(每类 799)。
- 所有类别都高频的特征(rice/garlic/ginger)没有区分度,删掉是特征选择不是损失。
- 数据备好了,上分类器:参见第 7 课《分类器:选择思路与多分类器对比》。
扩展阅读
- 原课第 6 课:https://github.com/microsoft/ML-For-Beginners/tree/main/4-Classification/1-Introduction
- imbalanced-learn 官方文档(SMOTE 及更多采样方法):https://imbalanced-learn.org/stable/
- SMOTE 原论文(Chawla et al., 2002, JAIR):https://www.jair.org/index.php/jair/article/view/10302
系列导航
- 上一篇:第 05 课《把模型做成 Web 应用(UFO)》
- 下一篇:第 07 课《分类器:选择思路与多分类器对比》
更多专栏:
| 蛋白 / 抗体 / 多肽 / 核酸 | 分子模拟 / 动力学 / 对接 | 药物 / 设计 / 案例 | AI / Agent / 大模型 |
|---|---|---|---|
| 开源蛋白结构预测 | 分子模拟基础 | 小分子药物设计案例 | AI Agent系列 |
| 开源蛋白生成方法实践 | 分子动力学模拟-Amber | 蛋白药物设计案例 | 化学大模型 |
| 开源多肽设计模型 | 分子动力学模拟-Gromacs | 多肽药物设计案例 | 《AI Agent原理与实战》 |
| 开源多肽性质预测 | 分子动力学模拟-OpenMM | 开源小分子生成设计 | CADD中的机器学习模型 |
| DNA/RNA药物设计 | 結合自由能 | 高效计算配置 | 《MCP 入门实战》 |
| siRNA药物设计模型 | UCSF DOCK系列 | 我胡师兄说药 | 《AI入门实战2026》 |
| ASO药物设计模型 | rDock系列 LeDock系列 gnina系列 | 《经典机器学习实战》 |