首页
/ ML-For-Beginners 参数实验(Parameter Play):菜系分类器参数调优实战指南

ML-For-Beginners 参数实验(Parameter Play):菜系分类器参数调优实战指南

2026-09-07 13:51:13作者:胡易黎Nicole

面向经典 ML 教学课程 ML-For-Beginners 中「Cuisine Classifiers 2」(菜系分类器进阶篇)一课的分支作业,本文围绕 assignment 要求的「参数实验」展开:以分类器默认参数为起点,系统化地调整 Linear SVC、SVC、K-Neighbors、Random Forest、AdaBoost 等分类器的关键参数并重新训练模型,通过观察准确率与分类报告的变化,回答"哪些参数调整提升了模型质量、哪些反而使其劣化,以及为什么"。读完本文,你将掌握一套可复现的参数实验方法,并能交付一个结构清晰、用文本单元格解释每个改动的评估用 Notebook。

本作业对应的英文原始文件位于 assignment.md,本课的完整正文(含全部分类器实验与指标输出)位于 README.md,参考实现可对照 solution/notebook.ipynb

作业要求解读:为什么需要"玩参数"

本课使用的每个 scikit-learn 分类器在实例化时都有大量默认参数。作业要求你做四件事:

  1. 从本课涉及的多种分类技术中选取一种作为主线研究对象;
  2. 通过 VS Code 的 Intellisense(在 Jupyter Notebook 代码单元格中输入 ClassifierName( 后弹出的签名与文档提示)深入挖掘每个参数的含义;
  3. 逐次调整参数值并重新训练模型,记录每次的结果;
  4. 构建一个 Notebook,在 Markdown 文本框(textbox)中详细解释:为什么某些改动提升了模型质量,为什么另一些改动使其劣化。

判断学生完成质量的标准(Rubric)非常明确:

标准 优秀(Exemplary) 合格(Adequate) 需改进(Needs Improvement)
整体 提交的 Notebook 完整构建了一个分类器,完成参数调整,并用文本框解释了各改动的效果 Notebook 部分完成或解释不充分 Notebook 存在错误或有缺陷

即:判定重心不是"调出了最高准确率",而是能否把每个参数改动与模型质量变化的因果关系讲清楚

实验素材:本课分类器与关键参数速览

先回顾本课在 README.md 中演示的分类器队列。数据来自 4-Classification 目录下已清洗的 cleaned_cuisines.csv(Notebook 中通过 pd.read_csv("../data/cleaned_cuisines.csv") 加载,仓库内实际路径为 data/cleaned_cuisines.csv),特征为各菜品出现的食材(0/1 编码),标签为 cuisine(chinese / indian / japanese / korean / thai 五类)。数据划分固定为 70% 训练、30% 测试:

X_train, X_test, y_train, y_test = train_test_split(
    cuisines_features_df, cuisines_label_df, test_size=0.3
)

课程依次构造的分类器及关键参数如下,这就是你"参数实验"的对象集:

分类器 课程中的构造方式 涉及的关键参数 本课基线准确率
Linear SVC SVC(kernel='linear', C=C, probability=True, random_state=0) kernelCprobabilityrandom_state 78.6%
KNN classifier KNeighborsClassifier(C) 第一个位置参数即 n_neighbors 73.8%
SVC SVC() 默认 kernel='rbf'Cgamma 83.2%
RFST(随机森林) RandomForestClassifier(n_estimators=100) n_estimatorsmax_depth 84.5%
ADA(AdaBoost) AdaBoostClassifier(n_estimators=100) n_estimatorslearning_rate 72.4%

值得注意的细节:KNeighborsClassifier(C)

课程演示代码中出现了 KNeighborsClassifier(C),这里 C 取自此前定义的 C = 10。由于 KNeighborsClassifier 的第一个位置参数是 n_neighbors,因此这句代码实际创建的是 n_neighbors=10 的近邻分类器。这说明参数是按位置绑定而非按名称绑定——这正是一个绝佳的实验切入点:显式写出 KNeighborsClassifier(n_neighbors=5)n_neighbors=10n_neighbors=15,观察近邻数如何影响分类边界。

参数背后的默认值与作用原理

要在实验中做出有依据的预测,需要先理解各参数在模型层面的角色:

  • C(正则化参数):SVC 中 C 控制误分类惩罚与决策边界平滑度之间的权衡。课程原文明确说明 C 指"正则化"(regularization),调节"参数的影响力"。可以推断的方向是:C 过小会倾向于"宽边界但容忍更多误分类"(偏向欠拟合),C 过大会不惜代价拟合每个训练点(偏向过拟合),因此存在一个让验证精度最优的区间。作业即建议你扫描 C 的多个取值(如 0.01、0.1、1、10、100)来验证这一趋势。
  • kernel(核函数):SVC 依赖"核"决定如何在特征空间划分类别。本课先以 kernel='linear' 得到线性决策面,随后 SVC() 使用默认的 RBF 核取得更高精度(83.2%)。可推断非线性核能刻画食材共现中更复杂的类别边界,但也更易过拟合。
  • probabilityrandom_stateprobability=True 让模型在训练后额外校准概率估计(课程中用于收集各类别概率);random_state=0 固定内部随机性,保证"打乱数据得到概率"的过程可复现。实验时若改动 random_state 导致结果波动,这本身就说明该模型的方差特性。
  • n_neighbors(KNN):KNN 通过"预定义的邻近点数"收集样本、投票决定标签。可推断较小的 k 边界更"曲折"、噪声敏感;较大的 k 更平滑,但可能在类别交界处把少数类"淹没"。由于本数据集五类样本量接近,用奇数 k 可减少平票问题。
  • n_estimators(集成树数量):随机森林"组合多棵决策树并注入随机性以避免过拟合",n_estimators 即树的数量;AdaBoost 则迭代地拟合同一分类器的副本,并"聚焦于被错分样本的权重"。可推断增大 n_estimators 通常提升稳定性与精度,但边际收益递减且训练时间上升;AdaBoost 还受 learning_rate 影响——步长过大可能震荡、过小收敛过慢。

实验方法:一次一个变量,记录完整证据链

围绕作业要求,推荐按下列流程组织实验,每个阶段都在 Notebook 中留下可复现的单元格:

第 1 步:搭建统一评估脚手架

沿用课程示例建立"分类器字典 + 统一训练评估"的循环,作为实验骨架:

from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
import numpy as np

C = 10

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))

输出中的 precision / recall / f1-score 与每类的 support 比单一准确率更能暴露问题——例如某类 precision 骤降往往意味着模型把它"误分"成了其他类。

第 2 步:用一组对照实验只改一个参数

实验设计应遵循"控制变量"原则:每次只调整一个参数,其余保持课程基线不变。以 SVC 为例可建立如下实验矩阵:

实验编号 改动参数 取值序列 要回答的问题
A C 0.01 / 0.1 / 1 / 10 / 100 正则化强弱如何影响精度与过拟合?
B kernel 'linear' vs 'rbf' vs 'poly' 决策面复杂度带来的收益与风险?
C probability True vs False 概率校准是否影响评估耗时与精度?
D random_state 0 / 1 / 42 结果是否稳定可复现?
E n_neighbors(KNN) 1 / 3 / 5 / 10 / 20 近邻数对边界的平滑作用如何体现?
F n_estimators 10 / 50 / 100 / 200 树的数量是否带来单调提升?
G learning_rate(AdaBoost) 0.1 / 0.5 / 1.0 / 2.0 步长过大/过小的典型后果?

每个实验后,把 accuracy_scoreclassification_report 的关键行复制到 Markdown 文本框,形成一条"改动 → 结果 → 机理"的证据链。

第 3 步:解释"为什么变好或变差"

评估文档(README)给出的基线提供了一个天然参照系,方便你在文本框中撰写分析。可复用的解释框架有三种:

  • 偏差-方差权衡:当把 C 从 10 一路调大,SVC 的"过拟合"倾向增强——训练精度可能继续升高而测试精度回落;这是判别"参数改动损及泛化"的经典信号。反之 C 过小时测试精度同样下降,但此时模型在训练集上就已欠拟合。
  • 模型容量:从 kernel='linear' 换到默认 RBF 核,本质是提高模型的非线性表达能力——本课数据显示 SVC 精度从 78.6%(Linear SVC)提升到 83.2%,可作为"容量增加带来收益"的正面案例;但若继续提高容量而不做正则约束,收益会被过拟合侵蚀。
  • 方差与随机性:改动 random_state 若让精度大幅抖动,说明该参数组合下模型不稳定,此时增大 n_estimatorsn_neighbors 往往能摊平方差。

常见失误与规避建议

结合 Rubric 中"Notebook 有 bug 或缺陷"一栏,作业需要特别规避以下坑:

  1. 把标签列当成特征训练cuisines_label_df 只保留 cuisine 列,特征必须 drop(['Unnamed: 0', 'cuisine'], axis=1);若误留标签列会得到虚高精度,这一点在 notebook.ipynb 的数据准备单元格中有明确演示。
  2. KNN 传参混淆:课程示例 KNeighborsClassifier(C) 容易误导读者以为传的是"正则化参数",实际 C=10 落到了 n_neighbors 上。实验时务必使用关键字参数,并在文本框里指出这个容易踩坑的点。
  3. fit 时 y 的维度y_train 是 pandas Series,课程代码用 np.ravel(y_train) 展平,避免部分 sklearn 版本对列向量的警告或报错。
  4. 不记录基线:每次实验都应保留课程基线结果作为对照,否则"提升/劣化"无从谈起。
  5. 一次改多个参数:同时调整 Ckernelprobability 后,即使结果变化也无法归因,文本解释会失去说服力。

交付物与仓库对照

最终提交应是一个自包含的 .ipynb,其结构建议为:数据加载与划分 → 分类器字典与评估循环 → 若干"单参数对照实验 + Markdown 文本框" → 汇总对比表与结论段。评分关注点在于每个文本框是否同时包含实测数字机理解释

可在仓库中对照的参考资料:

完成参数实验后,你可以把总结出的"对当前菜系数据最有效的分类器 + 最优参数组合"延续到下一课的应用实践中,完成从"玩参数"到"用参数"的闭环。

登录后查看全文
热门项目推荐
相关项目推荐