ML-For-Beginners 实战:为「用南瓜回归模型重做 Flask Web 应用」拆解模型换血、输入改造与云端部署(Assignment: Try a different model) ML-For-Beginners 实战为「用南瓜回归模型重做 Flask Web 应用」拆解模型换血、输入改造与云端部署Assignment: Try a different model【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners本文是一篇围绕本仓库3-Web-App/1-Web-App课程课后作业Assignment “Try a different model”关联文档见 translations/bg/3-Web-App/1-Web-App/assignment.md英文原版见 3-Web-App/1-Web-App/assignment.md展开的完整实战指南。它教你如何在已经掌握了“把 Scikit-learn 训练好的回归模型序列化成.pkl再通过 Flask 提供 Web 推理”这一套链路之后回到回归章节2-Regression中选一个不同的模型把原有的“UFO 目击预测”Web 应用重写成风格与输入都与模型训练方式完全对齐的新应用并最终部署到云端。读完本文你将能独立完成从“重新选择与训练回归模型”到“改造表单输入字段、重写输出标签映射、本地联调、云端部署与按评分标准自检”的整条闭环并理解最容易踩坑的“输入形状与模型训练特征必须一致”这一核心原则。一、作业到底要求什么读懂 assignment 的三层意图该作业英文版与保加利亚语翻译版内容一致正文极短但信息量不小拆开看包含三个明确指令换模型你已经用“训练好的回归模型”构建过一个 Web 应用即 UFO 应用现在要从更早的回归课程2-Regression下的线性 / 多项式回归、逻辑回归课中挑一个模型来“redo”这个 Web 应用。换外观可选可以保留原有风格也可以围绕南瓜pumpkin数据重新设计界面因为被选中的回归模型几乎都基于南瓜数据集训练。必改输入务必将 Web 表单的输入项改成与所选模型训练时的特征features完全一致——这是本作业的题眼也是它区别于“照着抄一遍代码”的核心考察点。此外作业的评分表Rubric给出唯一的硬性验收标准等级标准优秀ExemplaryWeb 应用按预期运行并成功部署到云端合格AdequateWeb 应用存在缺陷或出现意外结果待改进Needs ImprovementWeb 应用无法正常工作也就是说作业的最终交付物是一个能跑、能上线的成品应用而不仅仅是 notebook 里的一个模型。所以下面所有环节都以“最终能在云端访问”为目标展开。二、被重做对象的基线UFO 应用是怎么工作的要“换模型重做”先得把当前应用的完整链路吃透。完整教案在 3-Web-App/1-Web-App/README.md成品代码直接放在仓库的 solution/web-app 目录对应的训练 notebook 是 notebook.ipynb完整带输出的版本在 solution/notebook.ipynb。整个链路可以归纳为五个阶段1. 数据清洗数据来自 NUFORC 的 8 万条 UFO 目击记录只保留对建模有用的 4 列duration (seconds)、country、latitude、longitude丢弃空值并只保留目击时长在 1–60 秒之间的记录import pandas as pd import numpy as np ufos pd.read_csv(./data/ufos.csv) ufos pd.DataFrame({Seconds: ufos[duration (seconds)], Country: ufos[country], Latitude: ufos[latitude], Longitude: ufos[longitude]}) ufos.dropna(inplaceTrue) ufos ufos[(ufos[Seconds] 1) (ufos[Seconds] 60)]2. 标签编码Country是文本需要变成数值。Scikit-learn 的LabelEncoder按字母序把Australia、Canada、Germany、UK、US编为0–4from sklearn.preprocessing import LabelEncoder ufos[Country] LabelEncoder().fit_transform(ufos[Country])⚠️ 注意编码结果本身没有被 pickled所以后面 Web 端在把输出3还原成国家名时app.py里手动维护了一个与字母序一一对应的列表countries [Australia, Canada, Germany, UK, US]。3. 训练逻辑回归模型用三个数值特征预测国家标签from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report from sklearn.linear_model import LogisticRegression 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) model LogisticRegression() model.fit(X_train, y_train) predictions model.predict(X_test) print(classification_report(y_test, predictions)) print(Accuracy: , accuracy_score(y_test, predictions))教案指出其准确率约95%Country与经纬度高度相关所以这个结果并不意外模型输入是3 个数值。4. 用 pickle 序列化模型import pickle model_filename ufo-model.pkl pickle.dump(model, open(model_filename, wb)) # 加载并验证输入 [50, 44, -12]秒数、纬度、经度应返回 3英国 model pickle.load(open(ufo-model.pkl, rb)) print(model.predict([[50, 44, -12]]))生成的ufo-model.pkl就存放在 solution 目录中与 Flask 应用同处一个目录树。5. Flask 应用消费模型目录结构web-app/static/css/styles.css、web-app/templates/index.html、web-app/app.py、web-app/requirements.txtrequirements.txt内容为scikit-learn / pandas / numpy / flask四行用pip install -r requirements.txt一键安装app.py完整代码见 solution/web-app/app.py的核心逻辑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)前端表单见 solution/web-app/templates/index.html用 Jinja2 模板的{{ }}语法渲染结果并把seconds / latitude / longitude三个输入 POST 到/predict路由debugTrue便于开发期热更新但如教案反复提醒生产环境不要开启 debug。这条链路的架构非常清晰也正因为如此“换一个模型重做”并不是推倒重来而是替换第 2–4 阶段的“数据/标签/特征”并同步修改表单与predict()中的输入取值顺序、二维数组整形方式以及输出解码表。三、候选模型盘点南瓜数据上能选谁作业要求“使用来自更早回归课程的一个模型”。在2-Regression章节课程大纲见 2-Regression/README.md中全部以北美南瓜价格数据2-Regression/data/US-pumpkins.csv为背景共四课其中后两课训练了真实模型都是本作业的候选候选 A线性 / 多项式回归——预测南瓜价格连续值对应 3-Linear 课程 及其 notebook。从 notebook 源码可以看出数据准备围绕价格展开原始列包含Package、Variety、City Name、Low Price、High Price、Date等清洗时按“bushel”计价口径换算、把日期折算成月份或年内第几天day-of-year最终目标是用回归拟合出一个连续的Price。预测目标连续的价格数值特征形态数值型例如把日期转成的 day-of-year 或 Month输出解码不需要类别映射表直接把回归值渲染成价格即可甚至可以做多项式/线性对比展示。候选 B逻辑回归——预测南瓜颜色二元分类对应 4-Logistic 课程 及其 notebook。该课发现南瓜数据里有一个天然的二元类别Color橙色 还是 白色 于是用逻辑回归做分类教案里先选出候选列[City Name,Package,Variety,Origin,Item Size,Color]再对类别型特征编码LabelEncoder/ 序数编码数据里可见ord__Item Size这样的编码后列名最后from sklearn.model_selection import train_test_split 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)在该课约 1000 行的南瓜数据上教案给出的分类报告显示总体 accuracy 约0.92F1-score 约0.7458参见 4-Logistic/README.md 中的输出。如何选考量维度候选 A价格线性/多项式回归候选 B颜色逻辑回归输出类型连续数值价格二元类别orange / white表单输入少、纯数值最容易做特征较多、多为类别特征需额外编码与原 UFO 应用差异大回归 vs 分类小同为逻辑回归、同为类别输出界面叙事“输入时间估算南瓜价格”“输入产地/品种/尺寸预测南瓜颜色”本文主推路线是改造出一个“南瓜价格/颜色预测”应用为了真正契合作业“重做redo”的要求而不是复制建议在 Notebook 里基于 3-Linear 或 4-Logistic 重新整理出一个特征精简、可被表单直接表达的模型详见第五节然后整体替换原 UFO 应用。四、核心原则输入必须服从训练方式作业原文特别强调“Be careful to change the inputs to reflect your models training method.”这背后是模型服务化的通用铁律——推理时喂给模型的每个特征、顺序、数据类型、甚至维度形状都必须与训练时完全一致。用 UFO 应用反推这个原则至少包含四点约束特征顺序predict()中request.form.values()是按 HTML 表单里input的出现顺序收集的因此index.html的字段顺序必须与训练时Selected_features [Seconds,Latitude,Longitude]的列顺序一致二维形状scikit-learn 的predict()要求输入是(n_samples, n_features)的二维数组所以代码里要做[np.array(int_features)]这一步整形少一层括号就会报 shape 错误数值类型Seconds/Latitude/Longitude都是数值服务端用int(x)/ 保留 float 做转换如果换成带小数点的价格或经纬度类输入要避免一刀切int()标签解码模型输出的是编码后的整数索引如3Web 端必须持有一份与LabelEncoder字母序完全一致的解码表否则会出现“预测正确但显示错国家”的隐蔽 bug。当你把模型换成南瓜模型时这四条约束每一项都可能被打破特征不再是 3 个而可能更多不再全是纯数字Variety、City Name、Origin是字符串输出不再映射 5 国而可能映射“orange/white”或直接是价格甚至输入取值域也从“秒 0–60”变成月份 1–12、Item Size 档位等。这就是第五、六节要一步步解决的问题。五、实战路线 A改造为“南瓜颜色预测”应用推荐这条路线从 4-Logistic 出发模型仍是逻辑回归但数据与标签换成南瓜。为了让表单可填、链路可复用 UFO 原有架构建议在 notebook 中把特征收敛为可直接填写的数值型列并在训练时把预处理管线一并 pickled这是比原 UFO 教程更进一步的最佳实践。Step 1重新清洗与准备数据在回归章节 Notebook 的基础上从 US-pumpkins.csv 读出数据并构建小型 DataFrameimport pandas as pd import numpy as np pumpkins pd.read_csv(../data/US-pumpkins.csv) # 示例把 Item Size 这类可排序文本编码成数值作为简易特征 df pumpkins[[Item Size, Color]].copy() df df.dropna() df[Item Size] df[Item Size].astype(category).cat.codes # 编码为数值档位 df.head()说明若想 100% 复刻课程模型可保留[City Name,Package,Variety,Origin,Item Size,Color]并用OneHotEncoder/OrdinalEncoder编码见 4-Logistic/README.md 中columns_to_select附近的预处理代码但那样 Web 表单就需要提供大量文本选项。作业允许自由设计本文示例选择精简特征路线以便演示“输入与训练一致”的核心逻辑。Step 2划分训练集并训练、评估沿用回归课程的标准流程test_size0.2, random_state0与课程保持一致from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import classification_report, f1_score X df.drop(columns[Color]) # 特征 y (df[Color] ORANGE).astype(int) # 把颜色变成 0/1 二元标签 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) preds model.predict(X_test) print(classification_report(y_test, preds)) print(F1:, f1_score(y_test, preds))Step 3把“模型 预处理”一起 pickleUFO 教程只 pickle 了模型导致编码逻辑需要在 Web 端重复维护。做“换模型”时强烈建议用 scikit-learn 的Pipeline把编码器与分类器打包后整体序列化这样 Web 端永远不需要知道编码细节import pickle from sklearn.pipeline import make_pipeline # 若想保留完整预处理可用 make_pipeline(encoder, LogisticRegression()) with open(pumpkin-color-model.pkl, wb) as f: pickle.dump(model, f)Step 4搭建新的 Flask 应用沿用 solution/web-app 的目录骨架新建web-app/内含static/css/、templates/、app.py、requirements.txt依赖四件套不变。核心改造点 1——表单输入templates/index.html把三个 UFO 输入替换成南瓜模型的特征输入form action{{ url_for(predict) }} methodpost input typenumber nameitem_size placeholderItem Size (encoded) requiredrequired / button typesubmit classbtnPredict pumpkin color/button /form p{{ prediction_text }}/p核心改造点 2——predict()的输入与解码import numpy as np from flask import Flask, request, render_template import pickle app Flask(__name__) model pickle.load(open(./pumpkin-color-model.pkl, rb)) app.route(/predict, methods[POST]) def predict(): # 取值顺序 表单顺序 训练特征顺序 features [float(x) for x in request.form.values()] final_features [np.array(features)] output int(model.predict(final_features)[0]) label orange if output 1 else white return render_template(index.html, prediction_textLikely pumpkin color: {}.format(label)) if __name__ __main__: app.run(debugTrue) # 生产环境请改为 debugFalse对比原版 app.py 可以看到唯一没变的是“取表单值 → 转二维数组 →model.predict→ 索引转可读文本 → 回填模板”的骨架变的是特征数量、取值转换函数float而非int、解码表orange/white而非五国列表。核心改造点 3——界面主题把 styles.css 的深色星空风格改成南瓜橙色调即可作业允许“design it differently to reflect the pumpkin data”。Step 5本地运行验证cd web-app pip install -r requirements.txt # scikit-learn / pandas / numpy / flask python app.py # 或 python3 app.py浏览器访问http://127.0.0.1:5000/填入合法Item Size值确认返回的是可读的颜色文本且与 notebook 中该样本的预测一致。这一步同时完成了作业评分表里“Web 应用按预期运行”的本地验证。六、实战路线 B改造为“南瓜价格预测”应用如果想体会“分类 → 回归”的更大幅度换血就选线性/多项式回归模型3-Linear。训练端目标变成连续价格Web 端有两点关键差异输出不再查表predict()直接格式化回归数值output model.predict([np.array(features)])[0] return render_template(index.html, prediction_textEstimated price: ${:.2f}.format(output))输入是时间/日期特征如把Date折算成的 month 或 day-of-year表单可用typenumbermin/max约束取值域例如月份输入min1 max12与原 UFO 表单min0 max60限制目击秒数的手法同源。这条路线更能体现“输入与训练方法对应”的迁移能力适合作为作业加分项或口头答辩素材。七、云端部署命中评分表的“优秀”档评分表的最高档要求应用“部署到云端”。部署时需要把握的原则关闭 debug以app.run(host0.0.0.0, port5000)去掉debugTrue启动避免调试器在公网暴露依赖锁定用pip freeze requirements.txt固化版本避免云端环境与本地不一致导致pickle反序列化失败——pickle 对 sklearn 版本敏感这是部署期最常见的隐性故障源模型文件随应用上传.pkl文件要作为静态资源部署到服务器例如平台对象存储或应用目录下并注意在app.py中使用与部署路径匹配的相对路径如./pumpkin-color-model.pkl平台选择常见做法是部署到任一支持 Python Web 的 PaaS/云主机把web-app/目录作为启动根目录通过平台提供的健康检查 URL 访问/与/predict验证。具体平台配置方式以你选用服务的官方文档为准。云端可访问后就完整满足了 Rubric 中“Web 应用运行正常且已部署到云端”的“优秀”标准。八、完成度自检清单对照 Rubric 逐条核验写完后建议对照作业的验收标准自查新应用使用的模型确实来自2-Regression的回归课程而不是又把 UFO 模型抄一遍表单input的数量、顺序、类型与训练特征列完全一致服务端取值后构造的是(1, n_features)形状的二维数组输出解码表与训练时的标签编码一一对应orange/white或直接输出价格界面主题体现南瓜数据可保留原风格但“reflect the pumpkin data”是加分点pip install -r requirements.txt后python app.py能本地跑通、无异常结果对应“Adequate”档的缺陷/意外结果红线应用已部署到云端并能通过公网 URL 完成一次完整预测对应“Exemplary”档。九、延伸挑战把训练也搬进 Flask回归课程教案在 3-Web-App/1-Web-App/README.md 的 Challenge 中提出过一个进阶命题与其在 notebook 里训练再 import 模型不如在 Flask 应用内直接开一个train路由完成训练。把这个思路迁移到本次作业就是让应用同时具备“数据清洗 → 训练 → pickle → 预测”的全流程能力。可以从两个角度评估该方案的取舍优点是模型与代码的版本耦合更紧密、部署链路更简单缺点是每次启动/训练都消耗计算资源、训练数据需随应用分发且对请求并发与安全边界要求更高——这些问题恰好是理解“生产环境为什么通常把训练与推理分离”的最佳切入点。至此一次完整的“换模型重做 Web 应用”作业闭环全部完成从 assignment 的任务解读到回归模型的重新选择与训练再到 Flask 应用的输入改造、输出解码、本地验证、云端部署与评分自检每一步都有仓库内的教案、notebook 与 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),仅供参考