# Webアプリで機械学習モデルを活用する このレッスンでは、機械学習モデルをトレーニングし、ユニークなデータセットを使用します。それは、_過去100年間のUFO目撃情報_ であり、NUFORCのデータベースから取得されたものです。 学ぶ内容: - トレーニング済みモデルを「ピクル化」する方法 - Flaskアプリでそのモデルを使用する方法 ノートブックを使ってデータをクリーンアップし、モデルをトレーニングする作業を続けますが、さらに一歩進めて、モデルを「実際の環境」で使用する方法を探ります。つまり、Webアプリでの活用です。 これを実現するには、Flaskを使用してWebアプリを構築する必要があります。 ## [講義前のクイズ](https://ff-quizzes.netlify.app/en/ml/) ## アプリを構築する 機械学習モデルを利用するWebアプリを構築する方法は複数あります。Webアーキテクチャは、モデルのトレーニング方法に影響を与える可能性があります。例えば、データサイエンスチームがトレーニングしたモデルをアプリで使用するよう求められるビジネス環境を想像してみてください。 ### 考慮事項 以下のような質問をする必要があります: - **Webアプリかモバイルアプリか?** モバイルアプリを構築する場合やIoT環境でモデルを使用する必要がある場合、[TensorFlow Lite](https://www.tensorflow.org/lite/)を使用して、AndroidやiOSアプリでモデルを活用できます。 - **モデルはどこに配置されるのか?** クラウドかローカルか? - **オフライン対応。** アプリはオフラインで動作する必要があるか? - **モデルのトレーニングに使用された技術は何か?** 選択された技術は、使用するツールに影響を与える可能性があります。 - **TensorFlowを使用する場合。** 例えば、TensorFlowを使用してモデルをトレーニングする場合、そのエコシステムは[TensorFlow.js](https://www.tensorflow.org/js/)を使用してWebアプリでモデルを活用するための変換機能を提供します。 - **PyTorchを使用する場合。** [PyTorch](https://pytorch.org/)のようなライブラリを使用してモデルを構築する場合、[ONNX](https://onnx.ai/) (Open Neural Network Exchange)形式でエクスポートし、[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 (Software as a Service)システムを使用してモデルをトレーニングする場合、この種のソフトウェアは、クラウドでオンラインアプリがクエリを実行するためのカスタムAPIを構築するなど、さまざまなプラットフォーム向けにモデルをエクスポートする方法を提供します。 また、ブラウザ内でモデルをトレーニングできるFlask Webアプリ全体を構築することも可能です。これもJavaScript環境でTensorFlow.jsを使用して実現できます。 私たちの目的では、Pythonベースのノートブックを使用してきたので、トレーニング済みモデルをノートブックからPythonで構築されたWebアプリで読み取れる形式にエクスポートする手順を探ります。 ## ツール このタスクには、FlaskとPickleという2つのツールが必要です。どちらも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オブジェクト構造をシリアル化およびデシリアル化します。モデルを「ピクル化」する際には、その構造をシリアル化またはフラット化してWebで使用できるようにします。ただし、Pickleは本質的に安全ではないため、ファイルを「アンピクル化」するよう求められた場合は注意してください。ピクル化されたファイルの拡張子は`.pkl`です。 ## 演習 - データをクリーンアップする このレッスンでは、[NUFORC](https://nuforc.org) (The National UFO Reporting Center) によって収集された80,000件のUFO目撃情報を使用します。このデータには、以下のような興味深い目撃情報の説明が含まれています: - **長い説明の例。** 「夜の草原に光のビームが照らされ、そこから男性が現れ、テキサスインスツルメンツの駐車場に向かって走る」 - **短い説明の例。** 「光が私たちを追いかけてきた」 [ufos.csv](../../../../3-Web-App/1-Web-App/data/ufos.csv)スプレッドシートには、目撃が発生した`city`、`state`、`country`、物体の`shape`、およびその`latitude`と`longitude`に関する列が含まれています。 このレッスンに含まれる空白の[ノートブック](../../../../3-Web-App/1-Web-App/notebook.ipynb)で以下を行います: 1. 前のレッスンで行ったように`pandas`、`matplotlib`、`numpy`をインポートし、UFOスプレッドシートをインポートします。サンプルデータセットを確認できます: ```python import pandas as pd import numpy as np ufos = pd.read_csv('./data/ufos.csv') ufos.head() ``` 1. UFOデータを新しいタイトルで小さなデータフレームに変換します。`Country`フィールドのユニークな値を確認してください。 ```python ufos = pd.DataFrame({'Seconds': ufos['duration (seconds)'], 'Country': ufos['country'],'Latitude': ufos['latitude'],'Longitude': ufos['longitude']}) ufos.Country.unique() ``` 1. 必要なデータ量を減らすために、null値を削除し、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. トレーニングする3つの特徴をXベクトルとして選択し、yベクトルは`Country`になります。`Seconds`、`Latitude`、`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`と`Latitude/Longitude`が相関しているため、当然の結果です。 作成したモデルは非常に革新的なものではありませんが、クリーンアップした生データからトレーニングし、エクスポートしてWebアプリで使用する練習としては良い例です。 ## 演習 - モデルを「ピクル化」する 次に、モデルを「ピクル化」します!数行のコードでこれを実現できます。ピクル化された後、ピクル化されたモデルをロードし、秒数、緯度、経度の値を含むサンプルデータ配列でテストします。 ```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. そのフォルダ内にさらに3つのフォルダを作成します: **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. 次に、アプリを完成させるためにさらに3つのファイルを作成します: 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 }}