ML-For-Beginners 分类进阶:基于 Scikit-learn 路线图的五款分类器对比实战(Cuisine Classifiers 2)
本文基于 ML-For-Beginners 课程 4-Classification 章节的第二课「Cuisine classifiers 2」展开:以一份 3995 条、五国料理类别均衡的菜谱数据集为对象,沿着 Scikit-learn 官方算法路线图的决策路径,依次实战 Linear SVC、K-Neighbors、SVC(RBF 核)、Random Forest 与 AdaBoost 五款分类器,记录各自的训练代码、分类报告与准确率表现。读完后你能掌握"按数据画像选择估计器"的决策方法,以及每个分类器关键超参数(C、n_neighbors、n_estimators 等)的含义与调参思路。
前置条件与数据准备
本课程的默认假设是:你已经完成了分类章节的前序课程,并且在本四课文件夹根目录的 data 文件夹中有一份清洗好的数据集 cleaned_cuisines.csv(该数据集由 Lesson 1 中整理得到)。
从实际数据文件可以确认其规模:
- 共 3995 行样本、382 列;
- 第一列为行索引
Unnamed: 0,第二列为标签列cuisine,其余 380 列为二值化的食材特征(0/1,表示该菜谱是否含某种食材); - 五个类别完全均衡:indian、thai、chinese、japanese、korean 各 799 条。
本课程的 notebook.ipynb 已预置好数据加载代码,把数据集拆成了模型构建所需的两部分:
import pandas as pd
cuisines_df = pd.read_csv("../data/cleaned_cuisines.csv")
cuisines_df.head()
cuisines_label_df = cuisines_df['cuisine']
cuisines_label_df.head()
cuisines_features_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1)
cuisines_features_df.head()
从 notebook 的四个单元格结构看,准备工作只做了三件事:读入 CSV、取出 cuisine 列作为标签 y、剔除索引列和标签列后剩余 380 列食材特征作为 X。数据以 DataFrame 形式就位后,即可进入建模环节。该课程还提供了一份 R 语言平行实现 lesson_12.Rmd,供使用 R 生态的读者参考。
一张分类路线图:如何"走路"到决策
上一课(Cuisine classifiers 1)中,课程使用微软的机器学习选择 cheat sheet 来介绍分类选项。本课则引入 Scikit-learn 版本——一张更细粒度的算法路线图(即文首的 map.png),它把分类、回归、聚类、降维四大任务按"样本量、是否有标签、是否预测类别/数值"等维度组织成可点击的决策树。
当你已经对数据有清晰把握时,可以沿着图上的分支"走"出一条确定的路线。对本数据集而言,决策过程是:
- 样本数 > 50(实际 3995 条);
- 目标是预测一个类别(cuisine);
- 数据是有标签的(监督学习);
- 样本数 < 10 万;
- 于是路线指向 ✨ Linear SVC(线性支持向量分类器);
- 如果效果不佳——由于我们的数据是数值型特征——可以继续尝试 ✨ KNeighbors Classifier;
- 仍不理想时,升级到 ✨ SVC 与 ✨ Ensemble Classifiers(集成分类器)。
这正是本课实验的完整脚本:五个分类器,按路线图顺序逐一登场。
实验准备:导入库并划分训练/测试集
导入所需库
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score, precision_score, confusion_matrix, classification_report, precision_recall_curve
import numpy as np
划分训练集与测试集
X_train, X_test, y_train, y_test = train_test_split(cuisines_features_df, cuisines_label_df, test_size=0.3)
test_size=0.3 意味着约 30% 的样本(1199 条)进入测试集,其余约 2796 条用于训练——后续每份 classification_report 中的 support 合计 1199 正对应这个划分。
Linear SVC 分类器
支持向量分类(SVC)属于支持向量机(SVM)家族的一个分支。SVC 的关键参数在本课中都有明确取值:
| 参数 | 本课取值 | 含义 |
|---|---|---|
kernel |
'linear' |
核函数,决定如何划分类别簇;取 'linear' 即利用 Linear SVC |
C |
10 |
正则化强度,约束参数(权重)的影响大小 |
probability |
True |
默认关闭;打开后可获得概率估计 |
random_state |
0 |
固定随机种子,配合概率估计时对数据洗牌过程可复现 |
实验:构建分类器字典并训练
课程建议用一个字典统一管理所有分类器,后续每测试一款就向字典追加一项:
C = 10
# Create different classifiers.
classifiers = {
'Linear SVC': SVC(kernel='linear', C=C, probability=True, random_state=0)
}
然后按统一流程训练并打印分类报告:
n_classifiers = len(classifiers)
for index, (name, classifier) in enumerate(classifiers.items()):
classifier.fit(X_train, np.ravel(y_train))
y_pred = classifier.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy (train) for %s: %0.1f%% " % (name, accuracy * 100))
print(classification_report(y_test, y_pred))
两个值得注意的源码细节:其一,np.ravel(y_train) 把标签 DataFrame 压平为一维数组,避免 fit 收到形状不符的二维标签;其二,打印语句虽写着 "Accuracy (train)",实际计算的是 accuracy_score(y_test, y_pred),即测试集准确率——阅读输出时不要混淆。
Linear SVC 的结果已经相当不错(测试集准确率 78.6%):
Accuracy (train) for Linear SVC: 78.6%
precision recall f1-score support
chinese 0.71 0.67 0.69 242
indian 0.88 0.86 0.87 234
japanese 0.79 0.74 0.76 254
korean 0.85 0.81 0.83 242
thai 0.71 0.86 0.78 227
accuracy 0.79 1199
macro avg 0.79 0.79 0.79 1199
weighted avg 0.79 0.79 0.79 1199
K-Neighbors 分类器
K-Neighbors 属于机器学习中的"邻居"方法族,同时可用于监督与无监督学习:先产生一组预先定义数量的参考点,把数据聚集在这些点周围,从而为数据预测泛化的标签。对本数据集,KNN 直接沿用了上面的 C = 10 作为邻居数。
实验:追加 KNN 到分类器字典
上一款分类器表现不错,但或许还能更好。在字典的 Linear SVC 项后补一个逗号,追加:
'KNN classifier': KNeighborsClassifier(C),
注意这里把 C 作为了 KNeighborsClassifier 的第一个位置参数,即 n_neighbors=10——同一个数值 10,在 SVC 里是正则化系数,在 KNN 里是邻居数,含义完全不同。
结果略逊于 Linear SVC(测试集准确率 73.8%):
Accuracy (train) for KNN classifier: 73.8%
precision recall f1-score support
chinese 0.64 0.67 0.66 242
indian 0.86 0.78 0.82 234
japanese 0.66 0.83 0.74 254
korean 0.94 0.58 0.72 242
thai 0.71 0.82 0.76 227
accuracy 0.74 1199
macro avg 0.76 0.74 0.74 1199
weighted avg 0.76 0.74 0.74 1199
从报告可以看出 KNN 的短板在 korean 类:precision 高达 0.94 但 recall 只有 0.58,即"判为韩料的多数是对的,但大量韩料菜谱被漏判"——邻居法在特征高度稀疏、维度高达 380 的食材空间中,受距离度量稀释的影响比线性模型更明显。
Support Vector 分类器(默认 RBF 核)
支持向量分类器是 SVM 家族的成员,用于分类与回归任务。SVM 的直观思想是"把训练样本映射到空间中的点",并最大化两类之间的间隔;后续新数据被映射进这个空间后即可预测其类别。
实验:追加默认配置的 SVC
在 KNN 项后加逗号,追加一行:
'SVC': SVC(),
不传任何参数即采用 Scikit-learn 默认配置(默认核为 RBF,C=1.0)。结果有了明显提升,达到 83.2%:
Accuracy (train) for SVC: 83.2%
precision recall f1-score support
chinese 0.79 0.74 0.76 242
indian 0.88 0.90 0.89 234
japanese 0.87 0.81 0.84 254
korean 0.91 0.82 0.86 242
thai 0.74 0.90 0.81 227
accuracy 0.83 1199
macro avg 0.84 0.83 0.83 1199
weighted avg 0.84 0.83 0.83 1199
与 Linear SVC 对比可以看到:非线性 RBF 核把 korean 的 recall 从 0.81 提到 0.82 以上,chinese 的 precision 从 0.71 提到 0.79,说明食材特征之间的非线性组合关系确实存在且被 RBF 核捕捉到了。
集成分类器:Random Forest 与 AdaBoost
即使上一轮结果已经相当好,课程仍要求把路线图走到终点:尝试"集成分类器"——具体是 Random Forest 与 AdaBoost。
'RFST': RandomForestClassifier(n_estimators=100),
'ADA': AdaBoostClassifier(n_estimators=100)
两者的机制各有侧重:
- Random Forest 是一种"平均法"(averaging)集成:构建一片由随机性注入的"决策树森林"以避免过拟合;
n_estimators参数即树的棵数(本课设为 100)。 - AdaBoost 采用" boosting"策略:先对一个数据集拟合一个分类器,再用同样的分类器在同一数据上反复拟合,逐步把权重集中到被分错的样本上,并调整后续分类器的拟合以纠正这些错误。
结果中 Random Forest 成为全场最佳(84.5%),AdaBoost 则垫底(72.4%):
Accuracy (train) for RFST: 84.5%
precision recall f1-score support
chinese 0.80 0.77 0.78 242
indian 0.89 0.92 0.90 234
japanese 0.86 0.84 0.85 254
korean 0.88 0.83 0.85 242
thai 0.80 0.87 0.83 227
accuracy 0.84 1199
macro avg 0.85 0.85 0.84 1199
weighted avg 0.85 0.84 0.84 1199
Accuracy (train) for ADA: 72.4%
precision recall f1-score support
chinese 0.64 0.49 0.56 242
indian 0.91 0.83 0.87 234
japanese 0.68 0.69 0.69 254
korean 0.73 0.79 0.76 242
thai 0.67 0.83 0.74 227
accuracy 0.72 1199
macro avg 0.73 0.73 0.72 1199
weighted avg 0.73 0.72 0.72 1199
集成的本质是"融合多个基估计器的预测"以提升模型质量。Random Forest 在五个类别上的 precision/recall 全面均衡;AdaBoost 则暴露出典型问题——chinese 类 recall 仅 0.49,说明 boosting 对稀疏高维特征上的弱学习器组合并不占优。
五款分类器对比汇总
| 分类器 | 关键参数 | 测试集准确率 | 优势类别(按 f1) | 薄弱类别 |
|---|---|---|---|---|
| Linear SVC | kernel='linear', C=10, probability=True | 78.6% | indian (0.87) | chinese (0.69) |
| KNN | n_neighbors=10 | 73.8% | indian (0.82) | korean (0.72) |
| SVC(默认 RBF) | 默认参数 | 83.2% | indian (0.89) | chinese (0.76) |
| Random Forest | n_estimators=100 | 84.5% | indian (0.90) | chinese (0.78) |
| AdaBoost | n_estimators=100 | 72.4% | indian (0.87) | chinese (0.56) |
可以看出两个跨模型的规律:indian 类在所有分类器下都最易识别,chinese 类则始终最难——这提示类别难度既来自模型也来自特征本身的判别力;而"路线图顺序"(Linear SVC → KNN → SVC → Ensemble)在本数据上大体对应着准确率的爬升路径。
挑战与课后作业:玩转超参数
课程给出的挑战是:这些技术各自都有大量可调参数。去查阅它们的默认参数,并思考调整这些参数对模型质量意味着什么。
具体到本课用到的五个估计器,值得重点研究的参数包括:
- SVC / Linear SVC:
C(正则化强度)、kernel(linear/rbf/poly 等)、gamma、probability; - KNeighborsClassifier:
n_neighbors、weights('uniform' 或 'distance')、metric(距离度量)、p; - RandomForestClassifier:
n_estimators(树棵数)、max_depth、min_samples_split、class_weight; - AdaBoostClassifier:
n_estimators、learning_rate、algorithm(SAM/SAM_E/ADA); - 通用验证工具:
cross_val_score(本课导入但留给读者在挑战中实践)、confusion_matrix、precision_recall_curve。
正式作业见 assignment.md「Parameter Play」:选定本课任一分类技术,调整不同参数值重新训练,并产出一份解释"哪些改动提升了模型质量、哪些导致退化"的 notebook,评分标准(rubric)要求完整构建分类器、逐项调参并用文字解释每处改动。完整可运行的参考实现位于 solution/notebook.ipynb,其中分类器字典一次性包含全部五个估计器,训练循环与上文一致;R 语言版本参考 solution/R/lesson_12.Rmd。
小结
本课以一份 3995 条五类均衡的菜谱二值特征数据为载体,完整演示了"按 Scikit-learn 路线图选模型 → 逐一实验 → 用 classification_report 对比 → 归纳调参方向"的经典机器学习工作流。最终 Random Forest 以 84.5% 的测试集准确率胜出,而 AdaBoost 的落后则提醒我们:集成并非万能,算法选择必须结合数据特征(维度、稀疏度、类别结构)来判断。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00

