
ML-For-Beginners 分类实战全指南用亚洲与印度菜系数据完成从数据平衡、多分类建模到 ONNX 推荐 Web 应用【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners本文是 ML-For-Beginners 课程中「Einstieg in die Klassifikation分类入门」模块的完整技术指南。该模块围绕一份包含 2448 行、385 列的亚洲与印度菜系成分数据集展开通过四节递进课程分类基础、逻辑回归、SVC/KNN/集成学习、ONNX Web 应用演示经典机器学习分类的完整工作流。读完本文你将掌握如何用 SMOTE 平衡不均衡数据、如何为多分类问题选择分类器并解读 precision/recall/f1 指标、以及如何把 Scikit-learn 模型导出为 ONNX 并在纯前端 JavaScript 应用中做推理。模块总览一条从数据到产品的分类实战路径本模块是课程第四大部分建立在前面「回归Regression」学习的基础上将监督学习从预测连续数值延伸到预测离散类别。围绕根据一组食材判断其所属菜系这一核心问题四节课构成了完整的实战闭环课程主题仓库位置1分类入门数据清洗与类别平衡读取原始数据、探索食材分布、用 SMOTE 平衡类别2更多分类器逻辑回归用multi_classsolver参数做多分类逻辑回归3其他分类器SVC、KNN 与集成学习沿 Scikit-learn 决策地图依次尝试五种分类器4应用实战构建菜品推荐 Web 应用导出 ONNX 模型用 onnxruntime-web 在浏览器中推理模块配套的数据文件均位于 4-Classification/datacuisines.csv原始数据集2448 条记录每行是一种菜品的成分向量0/1 表示是否使用某食材385 列中 384 列为食材特征cleaned_cuisines.csv经过去噪、SMOTE 平衡后的干净数据集五个菜系各 799 条ingredient_indexes.csv380 个食材名称到 0~379 索引的映射表是后续 Web 应用 checkboxvalue的来源。各课的完整可运行代码见对应 solution 目录如4-Classification/2-Classifiers-1/solution/notebook.ipynb、4-Classification/4-Applied/solution/notebook.ipynb其中还提供了 R 语言版本如4-Classification/1-Introduction/solution/R/lesson_10-R.ipynb供对照学习。分类基础二分类与多分类分类是监督学习的一种形式与回归技术有很多共同点。回顾之前课程中的两种回归线性回归帮助预测变量间的关系并预测新数据点相对回归线的位置——例如预测南瓜在 9 月 vs 12 月的价格逻辑回归帮助发现二分类在某个价位上这个南瓜是橙色还是非橙色。分类则使用多种算法用其他方式判定数据点的标签label或类别class。分类方法会创建一个预测模型把输入变量与输出变量之间的映射关系建立起来。经典机器学习中的分类源自统计学通过smoker、weight、age等特征判定患 X 病的可能性——与之前回归练习相同你的数据是有标签的算法利用这些标签把数据归入某个组或结果。分类通常分为两大类二分类 vs 多分类问题示意图片来源ML-For-Beginners 课程插图二分类binary classification回答是/否类问题如这封邮件是不是垃圾邮件多分类multiclass classification在多个候选类别中择一如这组食材属于印度菜、泰国菜、中国菜、日本菜还是韩国菜。本模块要回答的正是多分类问题给定一批食材数据最可能属于五类国家菜系中的哪一类Scikit-learn 提供了多种分类算法接下来的课程将逐一使用。第一课数据清洗与类别平衡在开始建模前首要任务是清洗并平衡数据以获得更好的结果。从4-Classification/1-Introduction/notebook.ipynb空白笔记本开始。安装 imblearn 并导入数据imblearn是 Scikit-learn 生态中用于数据平衡的包本项目实际使用的是其中的SMOTE过采样技术pip install imblearn导入所需库包括imblearn.over_sampling中的SMOTEimport pandas as pd import matplotlib.pyplot as plt import matplotlib as mpl import numpy as np from imblearn.over_sampling import SMOTE读取原始数据并检查结构与内容df pd.read_csv(../data/cuisines.csv) df.head()前五行如下注意第一列是多余的Unnamed: 0索引列其后是cuisine标签列再后是数百个食材特征列| | Unnamed: 0 | cuisine | almond | angelica | anise | anise_seed | apple | apple_brandy | apricot | armagnac | ... | whiskey | white_bread | white_wine | whole_grain_wheat_flour | wine | wood | yam | yeast | yogurt | zucchini | | --- | ---------- | ------- | ------ | -------- | ----- | ---------- | ----- | ------------ | ------- | -------- | --- | ------- | ----------- | ---------- | ----------------------- | ---- | ---- | --- | ----- | ------ | -------- | | 0 | 65 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 66 | indian | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 2 | 67 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 3 | 68 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 4 | 69 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |用info()查看数据概要df.info()class pandas.core.frame.DataFrame RangeIndex: 2448 entries, 0 to 2447 Columns: 385 entries, Unnamed: 0 to zucchini dtypes: int64(384), object(1) memory usage: 7.2 MB探索各菜系的数据分布先看数据在五个菜系间的分布是否均衡df.cuisine.value_counts().plot.barh()可见菜系数量有限但分布很不均匀。分别统计每个菜系的样本量thai_df df[(df.cuisine thai)] japanese_df df[(df.cuisine japanese)] chinese_df df[(df.cuisine chinese)] indian_df df[(df.cuisine indian)] korean_df df[(df.cuisine korean)] print(fthai df: {thai_df.shape}) print(fjapanese df: {japanese_df.shape}) print(fchinese df: {chinese_df.shape}) print(findian df: {indian_df.shape}) print(fkorean df: {korean_df.shape})thai df: (289, 385) japanese df: (320, 385) chinese df: (442, 385) indian df: (598, 385) korean df: (799, 385)泰国菜只有 289 条而韩国菜多达 799 条——这种倾斜会直接导致模型偏向大类别必须处理。发现典型食材构建食材统计函数编写create_ingredient_df()函数丢弃无用的cuisine与Unnamed: 0列按出现次数对食材求和并降序排序def create_ingredient_df(df): ingredient_df df.T.drop([cuisine,Unnamed: 0]).sum(axis1).to_frame(value) ingredient_df ingredient_df[(ingredient_df.T ! 0).any()] ingredient_df ingredient_df.sort_values(byvalue, ascendingFalse, inplaceFalse) return ingredient_df对每个菜系调用并绘制 Top 10 食材对应图片见课程 READMEthai、japanese、chinese、indian、koreanthai_ingredient_df create_ingredient_df(thai_df) thai_ingredient_df.head(10).plot.barh() japanese_ingredient_df create_ingredient_df(japanese_df) japanese_ingredient_df.head(10).plot.barh() chinese_ingredient_df create_ingredient_df(chinese_df) chinese_ingredient_df.head(10).plot.barh() indian_ingredient_df create_ingredient_df(indian_df) indian_ingredient_df.head(10).plot.barh() korean_ingredient_df create_ingredient_df(korean_df) korean_ingredient_df.head(10).plot.barh()分析发现大米、大蒜、姜等食材几乎是所有菜系的公共项会在菜系间制造混淆因此需要剔除。用drop()去掉cuisine、Unnamed: 0以及这三个混淆食材同时单独保存标签列feature_df df.drop([cuisine,Unnamed: 0,rice,garlic,ginger], axis1) labels_df df.cuisine #.unique() feature_df.head()用 SMOTE 平衡数据集现在使用SMOTESynthetic Minority Over-sampling Technique合成少数类过采样技术平衡数据。其核心策略是fit_resample()——通过对少数类样本进行插值来生成新样本oversample SMOTE() transformed_feature_df, transformed_label_df oversample.fit_resample(feature_df, labels_df)为什么要平衡考虑二分类场景如果大部分数据都属于一个类别模型会因为该类的样本更多而更频繁地预测该类。平衡数据能消除这种偏差。对比平衡前后的标签计数print(fnew label count: {transformed_label_df.value_counts()}) print(fold label count: {df.cuisine.value_counts()})new label count: korean 799 chinese 799 indian 799 japanese 799 thai 799 Name: cuisine, dtype: int64 old label count: korean 799 indian 598 chinese 442 japanese 320 thai 289 Name: cuisine, dtype: int64五个菜系现在各 799 条完全均衡。最后把标签与特征拼接导出为后续课程共用的cleaned_cuisines.csvtransformed_df pd.concat([transformed_label_df,transformed_feature_df],axis1, joinouter) transformed_df.head() transformed_df.info() transformed_df.to_csv(../data/cleaned_cuisines.csv)课后可进一步探索 SMOTE 的 API思考它最适合哪些场景、解决了什么问题模块作业 Explore classification methods 要求你在 Scikit-learn 文档中寻宝为课程中的数据集匹配合适的分类方法与可提问的问题。第二课多分类逻辑回归与 solver 选择第二课使用上一课产出的平衡数据集目标是根据一组食材预测其所属国家菜系。准备数据与库import pandas as pd cuisines_df pd.read_csv(../data/cleaned_cuisines.csv) cuisines_df.head()导入建模所需库from sklearn.linear_model import LogisticRegression 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 from sklearn.svm import SVC import numpy as np拆出标签与特征cuisines_label_df cuisines_df[cuisine] cuisines_label_df.head()0 indian 1 indian 2 indian 3 indian 4 indian Name: cuisine, dtype: objectcuisines_feature_df cuisines_df.drop([Unnamed: 0, cuisine], axis1) cuisines_feature_df.head()特征列即各食材almond、angelica、anise……值为 0/1。选择分类器推理而非盲猜Scikit-learn 在 Supervised Learning 类别下提供了大量分类方法包括线性模型、支持向量机、随机梯度下降、最近邻、高斯过程、决策树、集成方法Voting Classifier、多分类与多输出算法等。面对如此多的选择课程给出了两条思路跑一遍对比Scikit-learn 在合成数据集上对 KNeighbors、SVC、GaussianProcessClassifier、DecisionTreeClassifier、RandomForestClassifier、MLPClassifier、AdaBoostClassifier、GaussianNB、QuadraticDiscrinationAnalysis 等做了并排对比图见 2-Classifiers-1/images/comparison.png查决策速查表更稳妥的做法是参考 Microsoft Algorithm Cheat Sheet图见 2-Classifiers-1/images/cheatsheet.png它针对多分类问题给出了候选算法清单。结合本任务约束进行推理神经网络太重数据集干净但很小且训练在本机笔记本中运行神经网络对这种任务过于重型不用二分类器因此排除 one-vs-all决策树或逻辑回归可行决策树或针对多分类数据的逻辑回归都可能是合适选择多分类提升决策树解决的是另一个问题它最适合非参数化任务如构建排序对本任务无用。理解multi_class与solver在 Scikit-learn 中做多分类逻辑回归必须指定两个关键参数multi_class决定训练策略。设为ovr时使用one-vs-restOvR方案设为multinomial时使用交叉熵损失该选项目前仅被lbfgs、sag、saga、newton-cg求解器支持。由于逻辑回归本质上是为二分类设计的这两种方案使其能够更好地处理多分类任务solver优化问题中使用的算法。并非所有 solver 都能与所有multi_class值配对。Scikit-learn 用一张表格说明不同 solver 如何应对不同类型数据结构的挑战图见 2-Classifiers-1/images/solvers.png。切分数据并训练逻辑回归X_train, X_test, y_train, y_test train_test_split(cuisines_feature_df, cuisines_label_df, test_size0.3)使用multi_classovr与liblinearsolver 创建并训练模型lr LogisticRegression(multi_classovr,solverliblinear) model lr.fit(X_train, np.ravel(y_train)) accuracy model.score(X_test, y_test) print (Accuracy is {}.format(accuracy))提示可以换用其他 solver如常被设为默认的lbfgs对比效果必要时使用 Pandas 的ravel把数据展平为一维。准确率超过80%。用单行数据第 50 行检验模型实际行为print(fingredients: {X_test.iloc[50][X_test.iloc[50]!0].keys()}) print(fcuisine: {y_test.iloc[50]})ingredients: Index([cilantro, onion, pea, potato, tomato, vegetable_oil], dtypeobject) cuisine: indian用predict_proba()查看该预测的概率分布test X_test.iloc[50].values.reshape(-1, 1).T proba model.predict_proba(test) classes model.classes_ resultdf pd.DataFrame(dataproba, columnsclasses) topPrediction resultdf.T.sort_values(by[0], ascending [False]) topPrediction.head()| | 0 | | -------: | -------: | | indian | 0.715851 | | chinese | 0.229475 | | japanese | 0.029763 | | korean | 0.017277 | | thai | 0.007634 |模型以 71.6% 的概率判断这是印度菜——香菜、洋葱、豌豆、土豆、番茄与植物油确实是典型的印度菜组合。最后打印分类报告y_pred model.predict(X_test) print(classification_report(y_test,y_pred))| | precision | recall | f1-score | support | | ------------ | --------- | ------ | -------- | ------- | | chinese | 0.73 | 0.71 | 0.72 | 229 | | indian | 0.91 | 0.93 | 0.92 | 254 | | japanese | 0.70 | 0.75 | 0.72 | 220 | | korean | 0.86 | 0.76 | 0.81 | 242 | | thai | 0.79 | 0.85 | 0.82 | 254 | | accuracy | | | 0.80 | 1199 | | macro avg | 0.80 | 0.80 | 0.80 | 1199 | | weighted avg | 0.80 | 0.80 | 0.80 | 1199 |印度菜识别效果最好f1 0.92日本菜相对较弱f1 0.72。课后作业 Study the solvers 要求任选两个 solver 对比它们解决什么问题、如何适配不同数据结构、为何选 A 不选 B。第三课沿决策地图尝试更多分类器第三课探索更多分类数值数据的方法并理解选择不同分类器的后果。Scikit-learn 提供了一张比 Microsoft 速查表更细粒度的ML Map机器学习地图图见 3-Classifiers-2/images/map.png可以沿路径走到决策样本数 50想预测一个类别数据有标签样本数 100K✨ 可以选择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 npX_train, X_test, y_train, y_test train_test_split(cuisines_features_df, cuisines_label_df, test_size0.3)Linear SVCSVC支持向量分类器属于支持向量机SVM技术家族。kernel决定如何聚类标签C是正则化参数调节参数的影响力probabilityTrue用于收集概率估计random_state0控制随机性以便复现C 10 # Create different classifiers. classifiers { Linear SVC: SVC(kernellinear, CC, probabilityTrue,random_state0) }统一训练并打印报告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))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 1199K-Neighbors 分类器K-Neighbors 属于邻居方法家族可用于监督与非监督学习预设一定数量的点数据围绕这些点聚集从而预测数据的广义标签。在分类器数组中追加KNN classifier: KNeighborsClassifier(C),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结果略差73.8%尤其韩国菜的 recall 只有 0.58。支持向量分类器SVCSVM 把训练样本映射到空间中的点最大化两个类别之间的距离之后新数据被映射到该空间以预测其类别。追加默认参数的 SVCSVC: SVC(),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 119983.2%比 Linear SVC 更好——默认的 RBF 核在数值稀疏数据上表现更佳。集成分类器Random Forest 与 AdaBoost集成方法组合多个基础估计器的预测来提升模型质量。追加随机森林100 棵树与 AdaBoost100 轮RFST: RandomForestClassifier(n_estimators100), ADA: AdaBoostClassifier(n_estimators100)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 Forest84.5% SVC83.2% Logistic Regression80% Linear SVC78.6% KNN73.8% AdaBoost72.4%。Random Forest是平均化方法构建注入随机性的决策树森林以避免过拟合n_estimators指定树的数量AdaBoost先拟合一个分类器再在同一数据集上拟合该分类器的副本重点提高对错分样本的权重让下一个分类器修正错误。课后挑战 Parameter play 建议你研究各分类器的默认参数微调后观察哪些改动提升模型质量、哪些反而恶化并写成带文字说明的 notebook。第四课导出 ONNX 模型并构建推荐 Web 应用机器学习最有价值的实际用途之一是构建推荐系统。本课用 SVC 训练分类模型将其转换为ONNX格式再用onnxruntime-web在纯 JavaScript 应用中做推理——这种架构无需 Python 后端可本地甚至离线运行。与 3-Web-App/1-Web-App 中pickle Flask的全栈 Python 方案形成互补。训练并导出模型先安装skl2onnx用于把 Scikit-learn 模型转换为 ONNX 格式!pip install skl2onnx import pandas as pddata pd.read_csv(../data/cleaned_cuisines.csv) data.head()去掉前两列索引与 cuisine 标签其余作为特征 X标签作为 yX data.iloc[:,2:] X.head() y data[[cuisine]] y.head()训练 SVC 模型沿用上一课效果较好的配置from sklearn.model_selection import train_test_split from sklearn.svm import SVC from sklearn.model_selection import cross_val_score from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_reportX_train, X_test, y_train, y_test train_test_split(X,y,test_size0.3)model SVC(kernellinear, C10, probabilityTrue,random_state0) model.fit(X_train,y_train.values.ravel())y_pred model.predict(X_test) print(classification_report(y_test,y_pred))precision recall f1-score support chinese 0.72 0.69 0.70 257 indian 0.91 0.87 0.89 243 japanese 0.79 0.77 0.78 239 korean 0.83 0.79 0.81 236 thai 0.72 0.84 0.78 224 accuracy 0.79 1199 macro avg 0.79 0.79 0.79 1199 weighted avg 0.79 0.79 0.79 1199转换时必须用正确的张量维度本数据集列出了 380 种食材因此FloatTensorType的第二维填 380from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType initial_type [(float_input, FloatTensorType([None, 380]))] options {id(model): {nocl: True, zipmap: False}}onx convert_sklearn(model, initial_typesinitial_type, optionsoptions) with open(./model.onnx, wb) as f: f.write(onx.SerializeToString())转换选项说明zipmapFalse分类模型默认会附带 ZipMap产生字典列表本场景不需要因此关闭noclTruenocl控制是否把类别信息包含进模型设为True可减小模型体积。运行整个 notebook 后即生成model.onnx文件与示例产物一致见 4-Classification/4-Applied/solution/model.onnx。用 Netron 检视模型ONNX 模型在 VS Code 中不可直接可视化可用 Netron 打开model.onnx检查结构——可以看到 380 个输入与分类器输出构建推荐 Web 应用在存放model.onnx的同级目录创建index.html参考完整示例 4-Classification/4-Applied/solution/index.html。先写基础骨架!DOCTYPE html html header titleCuisine Matcher/title /header body ... /body /html在body中加入食材复选框。每个 checkbox 的value对应食材在数据集中的索引——例如 apple 在按字母排序的列表中位于第 5 列从 0 开始计数所以是4索引完整映射见 ingredient_indexes.csvh1Check your refrigerator. What can you create?/h1 div idwrapper div classboxCont input typecheckbox value4 classcheckbox labelapple/label /div div classboxCont input typecheckbox value247 classcheckbox labelpear/label /div div classboxCont input typecheckbox value77 classcheckbox labelcherry/label /div div classboxCont input typecheckbox value126 classcheckbox labelfenugreek/label /div div classboxCont input typecheckbox value302 classcheckbox labelsake/label /div div classboxCont input typecheckbox value327 classcheckbox labelsoy sauce/label /div div classboxCont input typecheckbox value112 classcheckbox labelcumin/label /div /div div stylepadding-top:10px button onClickstartInference()What kind of cuisine can you make?/button /div在最后一个/div之后加入脚本块。首先引入 onnxruntime-web用于跨硬件平台运行 ONNX 模型并提供优化与 APIscript srchttps://cdn.jsdelivr.net/npm/onnxruntime-web1.9.0/dist/ort.min.js/script然后是推理逻辑script const ingredients Array(380).fill(0); const checks [...document.querySelectorAll(.checkbox)]; checks.forEach(check { check.addEventListener(change, function() { // toggle the state of the ingredient // based on the checkboxs value (1 or 0) ingredients[check.value] check.checked ? 1 : 0; }); }); function testCheckboxes() { // validate if at least one checkbox is checked return checks.some(check check.checked); } async function startInference() { let atLeastOneChecked testCheckboxes() if (!atLeastOneChecked) { alert(Please select at least one ingredient.); return; } try { // create a new session and load the model. const session await ort.InferenceSession.create(./model.onnx); const input new ort.Tensor(new Float32Array(ingredients), [1, 380]); const feeds { float_input: input }; // feed inputs and run const results await session.run(feeds); // read from results alert(You can enjoy results.label.data[0] cuisine today!) } catch (e) { console.log(failed to inference ONNX model); console.error(e); } } /script代码逻辑拆解创建长度 380 的数组值 1 或 0按复选框勾选状态发送给模型推理遍历所有 checkbox勾选时更新ingredients数组中对应索引的值testCheckboxes()校验是否至少勾选了一个食材点击按钮触发startInference()勾选后开始推理推理流程异步加载模型 → 创建[1, 380]形状的 Tensor → 构造feeds键名float_input与训练时定义的输入名一致可用 Netron 核对→ 送入模型并读取results.label.data[0]输出。本地运行与测试在存放index.html的目录打开 VS Code 终端全局安装并启动http-serverhttp-server浏览器打开 localhost 即可看到应用界面勾选不同食材组合查看推荐的菜系至此你已用分类模型构建了一个推荐Web 应用。课程挑战建议继续用 ingredient_indexes.csv 扩充食材清单与索引探索哪些风味组合能构成某道国菜模块作业 Build a recommender 则鼓励你举一反三用类似思路构建宠物推荐器或音乐风格推荐器。模块总结与进阶方向从数据清洗、SMOTE 类别平衡到多分类逻辑回归的参数调优、沿 Scikit-learn 决策地图横向对比五种分类器再到 ONNX 模型导出与浏览器端推理——本模块完整覆盖了经典机器学习分类从数据到产品的全流程。横向对比结论可作为后续建模的参考基准在本数据集上 Random Forest 与 SVC 的准确率最高KNN 与 AdaBoost 相对偏弱。后续深入方向包括研究各分类器默认参数并观察调参对模型质量的影响对应 Parameter play阅读 Scikit-learn 分类方法清单为课程其他数据集匹配合适算法对应 Explore classification methods以及把 ONNX 推荐架构迁移到其他推荐场景。所有课程的答案 notebook、R 语言版本与完整 HTML 报告均可在各课的 solution 目录中找到。【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考