# 构建一个使用机器学习模型的Web应用 在本课中,你将使用一个非常特别的数据集训练一个机器学习模型:_过去一个世纪的UFO目击事件_,这些数据来源于NUFORC的数据库。 你将学习到: - 如何“pickle”一个训练好的模型 - 如何在Flask应用中使用该模型 我们将继续使用notebook来清理数据和训练我们的模型,但你可以更进一步,探索在实际环境中使用模型:在一个web应用中。 要做到这一点,你需要使用Flask构建一个web应用。 ## [课前测验](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/17/) ## 构建应用 有几种方法可以构建web应用来使用机器学习模型。你的web架构可能会影响你训练模型的方式。想象一下,你在一个企业中工作,数据科学团队已经训练了一个模型,他们希望你在应用中使用。 ### 考虑因素 你需要问自己很多问题: - **这是一个web应用还是一个移动应用?** 如果你正在构建一个移动应用或需要在物联网环境中使用模型,你可以使用 [TensorFlow Lite](https://www.tensorflow.org/lite/) 并在Android或iOS应用中使用该模型。 - **模型将驻留在哪里?** 在云端还是本地? - **离线支持。** 应用是否需要离线工作? - **使用什么技术训练模型?** 所选技术可能会影响你需要使用的工具。 - **使用TensorFlow。** 如果你使用TensorFlow训练模型,例如,该生态系统提供了使用 [TensorFlow.js](https://www.tensorflow.org/js/) 将TensorFlow模型转换为web应用使用的能力。 - **使用PyTorch。** 如果你使用诸如 [PyTorch](https://pytorch.org/) 之类的库构建模型,你可以选择将其导出为 [ONNX](https://onnx.ai/) (开放神经网络交换) 格式,用于可以使用 [Onnx Runtime](https://www.onnxruntime.ai/) 的JavaScript web应用。这种选择将在未来的课程中探索,用于一个Scikit-learn训练的模型。 - **使用Lobe.ai或Azure Custom Vision。** 如果你使用诸如 [Lobe.ai](https://lobe.ai/) 或 [Azure Custom Vision](https://azure.microsoft.com/services/cognitive-services/custom-vision-service/?WT.mc_id=academic-77952-leestott) 之类的ML SaaS(软件即服务)系统训练模型,这类软件提供了为多种平台导出模型的方法,包括构建一个定制API,通过你的在线应用在云端查询。 你还有机会构建一个完整的Flask web应用,该应用可以在web浏览器中自行训练模型。这也可以在JavaScript环境中使用TensorFlow.js完成。 为了我们的目的,因为我们一直在使用基于Python的notebook,让我们来探索将训练好的模型从这样的notebook导出为一个Python构建的web应用可读的格式所需的步骤。 ## 工具 完成这项任务,你需要两个工具:Flask和Pickle,它们都运行在Python上。 ✅ 什么是 [Flask](https://palletsprojects.com/p/flask/)? 由其创建者定义为“微框架”,Flask提供了使用Python和一个模板引擎构建网页的基本web框架功能。看看 [这个学习模块](https://docs.microsoft.com/learn/modules/python-flask-build-ai-web-app?WT.mc_id=academic-77952-leestott) 来练习使用Flask构建。 ✅ 什么是 [Pickle](https://docs.python.org/3/library/pickle.html)? Pickle 🥒 是一个Python模块,用于序列化和反序列化Python对象结构。当你“pickle”一个模型时,你将其结构序列化或扁平化,以便在web上使用。注意:pickle本质上是不安全的,因此如果被提示“un-pickle”一个文件时要小心。一个pickled文件的后缀是 `.pkl`。 ## 练习 - 清理数据 在本课中,你将使用由 [NUFORC](https://nuforc.org)(国家UFO报告中心)收集的80,000个UFO目击事件数据。这些数据包含一些有趣的UFO目击描述,例如: - **长描述示例。** “一个人从夜间照在草地上的光束中出现,并跑向德州仪器的停车场”。 - **短描述示例。** “灯光追逐我们”。 [ufos.csv](../../../../3-Web-App/1-Web-App/data/ufos.csv) 电子表格包括关于`city`、`state`和`country`的列,记录了目击事件发生的地点、物体的`shape`、其`latitude`和`longitude`。 在本课包含的空白 [notebook](../../../../3-Web-App/1-Web-App/notebook.ipynb) 中: 1. 导入`pandas`、`matplotlib`和`numpy`,并导入ufos电子表格。你可以查看一个样本数据集: ```python import pandas as pd import numpy as np ufos = pd.read_csv('./data/ufos.csv') ufos.head() ``` 1. 将ufos数据转换为一个具有新标题的小数据框。检查`Country`字段中的唯一值。 ```python ufos = pd.DataFrame({'Seconds': ufos['duration (seconds)'], 'Country': ufos['country'],'Latitude': ufos['latitude'],'Longitude': ufos['longitude']}) ufos.Country.unique() ``` 1. 现在,你可以通过删除任何空值并仅导入1-60秒之间的目击事件来减少需要处理的数据量: ```python ufos.dropna(inplace=True) ufos = ufos[(ufos['Seconds'] >= 1) & (ufos['Seconds'] <= 60)] ufos.info() ``` 1. 导入Scikit-learn的`LabelEncoder`库,将国家的文本值转换为数字: ✅ LabelEncoder按字母顺序编码数据 ```python from sklearn.preprocessing import LabelEncoder ufos['Country'] = LabelEncoder().fit_transform(ufos['Country']) ufos.head() ``` 你的数据应该看起来像这样: ```output 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.783333 ``` ## 练习 - 构建你的模型 现在你可以通过将数据分为训练组和测试组来准备训练模型。 1. 选择你要训练的三个特征作为X向量,y向量将是`Country`. You want to be able to input `Seconds`, `Latitude` and `Longitude`,并获得一个国家ID以返回。 ```python 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_size=0.2, random_state=0) ``` 1. 使用逻辑回归训练你的模型: ```python 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` and `Latitude/Longitude` correlate. The model you created isn't very revolutionary as you should be able to infer a `Country` from its `Latitude` and `Longitude`,但这是一个从你清理、导出并在web应用中使用的原始数据中尝试训练的好练习。 ## 练习 - “pickle”你的模型 现在,是时候_pickle你的模型了!你可以用几行代码完成。一旦_pickle完毕,加载你的pickled模型并用包含秒数、纬度和经度值的样本数据数组进行测试, ```python import 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]])) ``` 模型返回**'3'**,这是英国的国家代码。太神奇了!👽 ## 练习 - 构建一个Flask应用 现在你可以构建一个Flask应用来调用你的模型并返回类似的结果,但以更具视觉吸引力的方式。 1. 先在_notebook.ipynb_文件所在的地方创建一个名为**web-app**的文件夹,其中包含你的_ufo-model.pkl_文件。 1. 在该文件夹中创建三个文件夹:**static**,其中包含一个**css**文件夹,以及**templates**。你现在应该有以下文件和目录: ```output web-app/ static/ css/ templates/ notebook.ipynb ufo-model.pkl ``` ✅ 参考解决方案文件夹以查看完成的应用 1. 在_web-app_文件夹中创建的第一个文件是**requirements.txt**文件。就像JavaScript应用中的_package.json_一样,该文件列出了应用所需的依赖项。在**requirements.txt**中添加以下几行: ```text scikit-learn pandas numpy flask ``` 1. 现在,通过导航到_web-app_运行此文件: ```bash cd web-app ``` 1. 在你的终端中键入`pip install`,以安装_requirements.txt_中列出的库: ```bash pip install -r requirements.txt ``` 1. 现在,你准备创建另外三个文件以完成应用: 1. 在根目录中创建**app.py**。 2. 在_templates_目录中创建**index.html**。 3. 在_static/css_目录中创建**styles.css**。 1. 使用一些样式构建_styles.css_文件: ```css 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; } ``` 1. 接下来,构建_index.html_文件: ```html
According to the number of seconds, latitude and longitude, which country is likely to have reported seeing a UFO?
{{ prediction_text }}