
用南瓜数据重做 Web App在 ML-For-Beginners 中替换模型并部署【免费下载链接】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 课程中构建 Web App 使用机器学习模型一节的课后作业展开你已经用 UFO 数据集训练了一个逻辑回归模型并通过 Flask 应用把 pickle 序列化后的模型暴露成网页表单现在任务要求你用回归章节2-Regression中的另一个模型重做这个 Web 应用——典型做法是用南瓜数据US-pumpkins.csv训练一个预测南瓜颜色的逻辑回归分类器并替换原有应用。读完本文你将掌握换模型、改输入、调模板、重新部署的完整套路理解模型输入形状与 Web 表单字段之间必须严格对齐的根本原因并收获可运行的源码级参考。一、作业原文解读任务到底要求做什么作业见 translations/es/3-Web-App/1-Web-App/assignment.md英文原版为 3-Web-App/1-Web-App/assignment.md的核心指令只有一句话现在你已经用训练好的回归模型构建了一个 Web 应用请使用前面回归课程中的某个模型重做这个 Web 应用。你可以保持原有样式也可以设计成反映南瓜数据的不同样式。务必修改输入字段使其适配你模型的训练方式。拆解出三个明确的可执行要点换模型模型不再来自 UFO 数据预测国家而是来自回归章节中基于南瓜数据的模型预测颜色等。改输入UFO 模型的输入是Seconds、Latitude、Longitude三个数值南瓜模型的特征完全不同表单必须随之重写。保部署评分标准Rubric中的卓越Exemplary档要求Web 应用按预期运行且已部署到云端。作业本身是引导性的其技术深度全部落在它所依托的两份文档上Web App 课程正文 3-Web-App/1-Web-App/README.md 与逻辑回归课程 2-Regression/4-Logistic/README.md。下面先完整回顾参考实现是如何工作的再给出换模型的具体改造方案。二、参考实现全流程回顾UFO 应用是怎么构建的课程正文用 NUFORC 的 UFO 目击数据80,000 条记录见 3-Web-App/1-Web-App/data/ufos.csv演示了完整的训练 → 序列化 → Web 消费链路。这是改造工作的基线务必吃透每一步。2.1 数据清洗把原始表压缩成训练用的小表在 3-Web-App/1-Web-App/notebook.ipynb 中第一步是从 CSV 抽取三列数值特征并处理缺失值import pandas as pd import numpy as np ufos pd.read_csv(./data/ufos.csv) ufos.head() # 压缩为只含训练所需列的小数据框 ufos pd.DataFrame({Seconds: ufos[duration (seconds)], Country: ufos[country], Latitude: ufos[latitude], Longitude: ufos[longitude]}) ufos.Country.unique() # 丢弃空值只保留目击时长 1~60 秒的记录 ufos.dropna(inplaceTrue) ufos ufos[(ufos[Seconds] 1) (ufos[Seconds] 60)] ufos.info()然后使用 Scikit-learn 的LabelEncoder把国家文本转换为数字注意LabelEncoder按字母顺序编码这一点对后面的数字 → 国家名反查映射很关键from sklearn.preprocessing import LabelEncoder ufos[Country] LabelEncoder().fit_transform(ufos[Country]) ufos.head()清洗后的数据形如Seconds Country Latitude Longitude 2 20.0 3 53.200000 -2.916667 3 20.0 4 28.978333 -96.645833 14 30.0 4 35.823889 -80.253611 23 60.0 4 45.582778 -122.352222 24 3.0 3 51.783333 -0.7833332.2 训练模型输入三维特征输出国家类别特征向量X取Seconds、Latitude、Longitude标签y取Country用 80/20 切分后训练逻辑回归from sklearn.model_selection import train_test_split Selected_features [Seconds,Latitude,Longitude] X ufos[Selected_features] y ufos[Country] X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state0) from sklearn.metrics import accuracy_score, classification_report from sklearn.linear_model import LogisticRegression model LogisticRegression() model.fit(X_train, y_train) predictions model.predict(X_test) print(classification_report(y_test, predictions)) print(Predicted labels: , predictions) print(Accuracy: , accuracy_score(y_test, predictions))课程说明该模型准确率约 95%原因并不意外——Country与Latitude/Longitude高度相关。这个模型本身并不革命性但它是理解训练、导出、再消费全流程的极佳练习。2.3 Pickle 序列化把模型变成.pkl文件用 Python 内置的pickle模块把模型对象序列化注意pickle 并非天生安全不要反序列化来路不明的文件序列化文件后缀为.pklimport pickle model_filename ufo-model.pkl pickle.dump(model, open(model_filename, wb)) # 重新加载并测试 model pickle.load(open(ufo-model.pkl, rb)) print(model.predict([[50, 44, -12]]))对[50, 44, -12]预测返回3即英国的编码值。仓库中的成品模型位于 3-Web-App/1-Web-App/solution/ufo-model.pkl。2.4 Flask 应用骨架目录结构与依赖在notebook.ipynb与ufo-model.pkl旁边新建web-app/目录内部再建static/css/与templates/web-app/ static/ css/ templates/ notebook.ipynb ufo-model.pklrequirements.txt声明依赖作用相当于 JavaScript 项目里的package.jsonscikit-learn pandas numpy flask安装后即可启动开发服务器cd web-app pip install -r requirements.txt python app.py # 或 python3 app.py2.5 三个核心文件样式、模板、路由仓库中完整的成品实现位于 3-Web-App/1-Web-App/solution/web-app/包含app.py、templates/index.html、static/css/styles.css、requirements.txt四个文件。样式文件static/css/styles.css黑底白字、居中排版的简洁风格定义了input最小宽度、.grid居中网格与.box卡片body { width: 100%; height: 100%; font-family: Helvetica; background: black; color: #fff; text-align: center; letter-spacing: 1.4px; font-size: 30px; } input { min-width: 150px; } .grid { width: 300px; border: 1px solid #2d2d2d; display: grid; justify-content: center; margin: 20px auto; } .box { color: #fff; background: #2d2d2d; padding: 12px; display: inline-block; }模板templates/index.html注意 Jinja2 模板语法——{{ }}双花括号包裹由应用传入的变量如{{ prediction_text }}表单通过methodpost把数据 POST 到/predict路由静态资源用url_for(static, filenamecss/styles.css)解析!DOCTYPE html html head meta charsetUTF-8 title UFO Appearance Prediction! /title link relstylesheet href{{ url_for(static, filenamecss/styles.css) }} /head body div classgrid div classbox pAccording to the number of seconds, latitude and longitude, which country is likely to have reported seeing a UFO?/p form action{{ url_for(predict)}} methodpost input typenumber nameseconds placeholderSeconds requiredrequired min0 max60 / input typetext namelatitude placeholderLatitude requiredrequired / input typetext namelongitude placeholderLongitude requiredrequired / button typesubmit classbtnPredict country where the UFO is seen/button /form p{{ prediction_text }}/p /div /div /body /html应用入口app.py这是理解模型如何被 Web 应用消费的关键。仓库成品3-Web-App/1-Web-App/solution/web-app/app.py与课程正文的差别仅在于模型路径成品用../ufo-model.pkl指向 web-app 上层import numpy as np from flask import Flask, request, render_template import pickle app Flask(__name__) model pickle.load(open(./ufo-model.pkl, rb)) app.route(/) def home(): return render_template(index.html) app.route(/predict, methods[POST]) def predict(): int_features [int(x) for x in request.form.values()] final_features [np.array(int_features)] prediction model.predict(final_features) output prediction[0] countries [Australia, Canada, Germany, UK, US] return render_template( index.html, prediction_textLikely country: {}.format(countries[output]) ) if __name__ __main__: app.run(debugTrue)运行逻辑拆解如下启动时加载依赖并创建 Flask 应用实例在模块加载阶段把ufo-model.pkl反序列化进内存模型只加载一次而不是每个请求都重新加载/路由渲染index.html表单/predict路由在表单提交后收集表单值并转为整数列表 → 包成 numpy 数组 → 交给model.predict()→ 用countries[output]把数字类别反查为可读文本 → 回传给模板渲染。 课程提示debugTrue模式下对应用代码的任何改动会立即生效无需重启服务器但绝不能在生产环境开启该模式。2.6 最需要理解的一点输入形状由训练方式决定课程正文明确指出用 Flask pickle 模型这种方式工作相对简单最难的是理解必须把什么形状的数据送给模型才能得到预测——这完全取决于模型是如何训练的。UFO 模型需要三个数据点秒数、纬度、经度才能得到一次预测所以表单恰好是三个输入框。这个原则正是本次作业务必修改输入的底层原因换了模型输入形状必然变化。三、选择替代模型南瓜颜色逻辑回归作业允许使用前面回归课程中的某个模型。回归章节2-Regression/包含工具、数据、线性回归、逻辑回归四个子课其中逻辑回归课 2-Regression/4-Logistic/README.md 提供了与本应用最契合的替代品——一个预测南瓜颜色橙色/白色的二分类逻辑回归模型数据来自 2-Regression/data/US-pumpkins.csv。为什么推荐它它是分类模型输出是离散类别天然适配表单提交 → 返回可读标签的展示模式特征可解释可以选用Item Size等数值化特征作为表单输入与 UFO 应用的三输入框结构有对称性课程自带完整评估分类报告、混淆矩阵、ROC/AUC可以顺带把评估环节引入 Web 应用改造。3.1 数据整理选择列并去空逻辑回归课第一步是从南瓜数据中选出与问题相关的列并去空columns_to_select [City Name,Package,Variety, Origin,Item Size, Color] pumpkins full_pumpkins.loc[:, columns_to_select] pumpkins.dropna(inplaceTrue)其中Color是二分类标签橙色ORANGE或白色WHITE。数据集中还有极少量 striped 类别实例太少且去空后自然消失故不使用。3.2 特征与标签编码南瓜数据几乎全是字符串列机器学习算法只吃数值因此必须先编码。课程区分了两类编码器序数编码器OrdinalEncoder适合有逻辑顺序的类别变量如Item Sizesml、med、med-lge、lge、xlge、jbo、exjbo 有明确的从小到大顺序from sklearn.preprocessing import OrdinalEncoder item_size_categories [[sml, med, med-lge, lge, xlge, jbo, exjbo]] ordinal_features [Item Size] ordinal_encoder OrdinalEncoder(categoriesitem_size_categories)独热编码器OneHotEncoder适合无顺序关系的名义变量如City Name、Package、Variety、Origin每个类别展开为 0/1 二进制列from sklearn.preprocessing import OneHotEncoder categorical_features [City Name, Package, Variety, Origin] categorical_encoder OneHotEncoder(sparse_outputFalse)ColumnTransformer把两个编码器合成一步并作用于对应列标签则用LabelEncoder转成 0/1from sklearn.compose import ColumnTransformer ct ColumnTransformer(transformers[ (ord, ordinal_encoder, ordinal_features), (cat, categorical_encoder, categorical_features) ]) ct.set_output(transformpandas) encoded_features ct.fit_transform(pumpkins) from sklearn.preprocessing import LabelEncoder label_encoder LabelEncoder() encoded_label label_encoder.fit_transform(pumpkins[Color]) encoded_pumpkins encoded_features.assign(Colorencoded_label)对于 Web 应用而言这一节有特别意义如果表单只暴露Item Size一个数值输入那么预测时就需要构造与训练时完全一致的独热特征结构即保证ColumnTransformer的列顺序与训练时相同。这也是输入必须匹配训练方式的一个具体体现。3.3 训练与评估分类报告、混淆矩阵、ROC划分训练/测试集test_size0.2, random_state0后训练from sklearn.model_selection import train_test_split from sklearn.metrics import f1_score, classification_report from sklearn.linear_model import LogisticRegression X encoded_pumpkins[encoded_pumpkins.columns.difference([Color])] y encoded_pumpkins[Color] X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state0) model LogisticRegression() model.fit(X_train, y_train) predictions model.predict(X_test) print(classification_report(y_test, predictions)) print(Predicted labels: , predictions) print(F1-score: , f1_score(y_test, predictions))在约 1000 行数据上课程给出的分类报告如下实际数值随数据与随机种子而定precision recall f1-score support 0 0.94 0.98 0.96 166 1 0.85 0.67 0.75 33 accuracy 0.92 199 macro avg 0.89 0.82 0.85 199 weighted avg 0.92 0.92 0.92 199 Predicted labels: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1] F1-score: 0.7457627118644068配合混淆矩阵可以更直观地评估Scikit-learn 中行是真实标签、列是预测标签from sklearn.metrics import confusion_matrix confusion_matrix(y_test, predictions) # 输出示例array([[162, 4], [ 11, 22]])预测 0预测 1真实 0TNFP真实 1FNTP其中 precision、recall、f1-score 的定义为Precision TP / (TP FP)检索出的实例中真正相关的比例Recall TP / (TP FN)相关实例中被成功检索出的比例F1-score (2 × precision × recall) / (precision recall)二者加权平均最好为 1、最差为 0Support每个标签出现的次数Accuracy (TP TN) / (TP TN FP FN)Macro Avg各标签指标的无权重均值Weighted Avg按 support 加权后的均值。ROC 曲线与 AUC 同样可用 Scikit-learn 绘制和计算from sklearn.metrics import roc_curve, roc_auc_score import matplotlib.pyplot as plt y_scores model.predict_proba(X_test) fpr, tpr, thresholds roc_curve(y_test, y_scores[:,1]) fig plt.figure(figsize(6, 6)) plt.plot([0, 1], [0, 1], k--) plt.plot(fpr, tpr) plt.xlabel(False Positive Rate) plt.ylabel(True Positive Rate) plt.title(ROC Curve) plt.show() auc roc_auc_score(y_test, y_scores[:,1]) print(auc)AUC 取值 0~1越接近 1 越好100% 正确的模型 AUC 为 1课程在对应数据上得到的 AUC 约为 0.975属于相当不错的水平。3.4 简化改造路线只暴露 Item Size 一个输入如果希望 Web 表单与 UFO 应用一样简单、少输入可以只选用Item Size作为唯一数值特征重训一个单特征逻辑回归这样表单只需要一个item size数字输入框model.predict([[size]])的输入形状与 UFO 应用的model.predict([[s, lat, lon]])完全同构改动量最小预测输出 0/1 后用[ORANGE, WHITE]或 Not White / White映射回可读文本。这条路线最贴近作业keep the style 或 redesign的两种自由度也是最容易交付并部署到云端的选择。四、改造 Flask 应用三步替换法无论选哪种特征组合改造都遵循同一个三步框架。第一步换模型文件在训练南瓜模型的 notebook 中执行 pickle 导出路径、文件名与 UFO 模型的ufo-model.pkl区分开import pickle model_filename pumpkin-model.pkl pickle.dump(model, open(model_filename, wb))第二步改 app.py 的模型加载与预测映射UFO 版与南瓜版的差异点集中在app.py的三处位置UFO 版南瓜版示例模型加载pickle.load(open(./ufo-model.pkl, rb))pickle.load(open(./pumpkin-model.pkl, rb))特征构造int_features [int(x) for x in request.form.values()]后包 numpy 数组依训练特征顺序构造同样的数组如[[int(request.form[item_size])]]类别反查countries [Australia, Canada, Germany, UK, US]labels [Not White, White]与LabelEncoder的 0/1 编码一一对应反查列表必须与训练时LabelEncoder的编码顺序一致否则会出现预测结果张冠李戴。这是最容易踩的坑。第三步改模板与样式templates/index.html中把三个输入框替换为南瓜模型需要的输入。若采用单特征路线核心表单部分大致为form action{{ url_for(predict)}} methodpost input typenumber nameitem_size placeholderItem Size requiredrequired min0 max6 / button typesubmit classbtnPredict pumpkin color/button /form p{{ prediction_text }}/p样式可沿用 3-Web-App/1-Web-App/solution/web-app/static/css/styles.css 的黑底白字风格作业允许保持原样式也可以改配色反映南瓜主题如橙/白只需同步调整 CSS 变量与.grid、.box布局即可。验证与运行cd web-app pip install -r requirements.txt # 依赖与 UFO 版相同scikit-learn、pandas、numpy、flask python app.py在浏览器访问本地地址输入表单值并提交观察预测文本是否合理例如小号南瓜返回白色、大号南瓜返回橙色的预期分布。若结果异常优先检查两处特征输入顺序是否与训练一致、类别映射表是否与LabelEncoder顺序一致。五、部署到云端从本地到生产评分标准把部署到云端列为卓越档的必要条件。由于本仓库只提供代码与文档仓库为只读不包含部署脚本部署属于标准 Flask 运维操作给出以下可行路线按项目实际环境选用其一云平台 PaaS将web-app/目录含app.py、templates/、static/、requirements.txt、pumpkin-model.pkl推送后平台会自动识别 Python 应用与依赖清单并启动容器化部署用 Dockerfile 声明 Python 基础镜像 →pip install -r requirements.txt→python app.py再推到任意容器平台生产注意事项关闭debugTrue把模型文件与代码一起打包或从对象存储按需下载建议把端口改为平台注入的环境变量如PORT。无论哪种方式部署前的最终验收都应回到评分标准本身。六、评分标准解读如何拿到卓越作业 Rubrictranslations/es/3-Web-App/1-Web-App/assignment.md只有一档矩阵三档表现标准卓越合格需改进应用行为Web 应用按预期运行且已部署到云端Web 应用存在缺陷或展示出意外结果Web 应用无法正常工作对照实现清单自查按预期运行表单输入 → 预测 → 展示可读结果全链路无报错预测结果与 notebook 中模型行为一致输入已按模型适配表单字段名、顺序、类型与训练特征严格对齐作业明文要求已部署到云端提供一个可公网访问的地址而非仅本地localhost成果可复现保留 notebook如 3-Web-App/1-Web-App/notebook.ipynb 同目录的南瓜训练 notebook与 pickle 模型让他人能复现整个链路。七、延伸思考在应用内部直接训练模型课程末尾的 Challenge 提出了一个更有意思的方向不把模型在 notebook 中训练好再导入 Flask而是在 Flask 应用内部完成训练——在数据清洗之后把训练代码搬进应用挂到名为train的路由上。权衡点包括优点模型与数据同源无需维护.pkl文件版本数据更新后一键重训对演示类应用更自洽缺点训练是 CPU 密集型操作放在 Web 进程内会阻塞请求、拉长响应时间模型状态保存在进程内存中重启即丢失数据清洗与训练的失败会直接影响 Web 服务可用性生产环境通常应把训练与推理分离。这个挑战没有标准答案但对理解模型训练与模型消费的架构边界极有价值——这也正是本作业想让你体会的核心在真实工程中训练模型的人和消费模型的人哪怕是同一个人之间必须靠特征顺序、输入形状、类别映射这三份契约来沟通。【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考