# Создание веб-приложения для использования ML модели В этом уроке вы обучите ML модель на уникальном наборе данных: _наблюдения НЛО за последний век_, взятые из базы данных NUFORC. Вы узнаете: - Как "запаковать" обученную модель - Как использовать эту модель в приложении Flask Мы продолжим использовать ноутбуки для очистки данных и обучения модели, но вы сможете сделать шаг дальше, исследуя использование модели "в реальных условиях", так сказать: в веб-приложении. Для этого вам нужно создать веб-приложение с использованием Flask. ## [Тест перед лекцией](https://ff-quizzes.netlify.app/en/ml/) ## Создание приложения Существует несколько способов создания веб-приложений для использования моделей машинного обучения. Ваша веб-архитектура может повлиять на способ обучения модели. Представьте, что вы работаете в компании, где группа специалистов по данным обучила модель, которую они хотят, чтобы вы использовали в приложении. ### Важные вопросы Есть множество вопросов, которые нужно задать: - **Это веб-приложение или мобильное приложение?** Если вы создаете мобильное приложение или вам нужно использовать модель в контексте IoT, вы можете использовать [TensorFlow Lite](https://www.tensorflow.org/lite/) и интегрировать модель в приложение для Android или iOS. - **Где будет находиться модель?** В облаке или локально? - **Поддержка оффлайн-режима.** Должно ли приложение работать без подключения к интернету? - **Какая технология использовалась для обучения модели?** Выбранная технология может повлиять на инструменты, которые вам нужно использовать. - **Использование TensorFlow.** Если вы обучаете модель с помощью TensorFlow, эта экосистема предоставляет возможность конвертировать модель TensorFlow для использования в веб-приложении с помощью [TensorFlow.js](https://www.tensorflow.org/js/). - **Использование PyTorch.** Если вы создаете модель с использованием библиотеки, такой как [PyTorch](https://pytorch.org/), у вас есть возможность экспортировать ее в формате [ONNX](https://onnx.ai/) (Open Neural Network Exchange) для использования в веб-приложениях на JavaScript, которые могут использовать [Onnx Runtime](https://www.onnxruntime.ai/). Этот вариант будет рассмотрен в будущем уроке для модели, обученной с помощью Scikit-learn. - **Использование Lobe.ai или Azure Custom Vision.** Если вы используете ML SaaS (Software as a Service) систему, такую как [Lobe.ai](https://lobe.ai/) или [Azure Custom Vision](https://azure.microsoft.com/services/cognitive-services/custom-vision-service/?WT.mc_id=academic-77952-leestott) для обучения модели, этот тип программного обеспечения предоставляет способы экспортировать модель для различных платформ, включая создание индивидуального API для запросов в облаке вашим онлайн-приложением. Вы также можете создать полноценное веб-приложение Flask, которое сможет обучать модель прямо в веб-браузере. Это также можно сделать с использованием TensorFlow.js в контексте JavaScript. Для наших целей, поскольку мы работали с ноутбуками на основе Python, давайте рассмотрим шаги, которые нужно предпринять, чтобы экспортировать обученную модель из такого ноутбука в формат, читаемый веб-приложением, созданным на Python. ## Инструменты Для этой задачи вам понадобятся два инструмента: Flask и Pickle, оба работают на Python. ✅ Что такое [Flask](https://palletsprojects.com/p/flask/)? Определяемый его создателями как "микро-фреймворк", Flask предоставляет базовые функции веб-фреймворков с использованием Python и движка шаблонов для создания веб-страниц. Ознакомьтесь с [этим модулем обучения](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 не является безопасным по своей природе, поэтому будьте внимательны, если вас попросят "распаковать" файл. Файл Pickle имеет суффикс `.pkl`. ## Упражнение - очистка данных В этом уроке вы будете использовать данные о 80,000 наблюдениях НЛО, собранных [NUFORC](https://nuforc.org) (Национальный центр сообщений о НЛО). Эти данные содержат интересные описания наблюдений НЛО, например: - **Длинное описание.** "Человек выходит из луча света, который освещает травяное поле ночью, и бежит к парковке Texas Instruments". - **Короткое описание.** "огни преследовали нас". Электронная таблица [ufos.csv](../../../../3-Web-App/1-Web-App/data/ufos.csv) включает столбцы о `городе`, `штате` и `стране`, где произошло наблюдение, форме объекта (`shape`) и его `широте` и `долготе`. В пустом [ноутбуке](../../../../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. Импортируйте библиотеку `LabelEncoder` из Scikit-learn для преобразования текстовых значений стран в числа: ✅ 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`. Вы хотите иметь возможность вводить `Seconds`, `Latitude` и `Longitude` и получать идентификатор страны. ```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` коррелируют. Созданная вами модель не является очень революционной, так как вы должны быть в состоянии определить `Country` по его `Latitude` и `Longitude`, но это хорошее упражнение для обучения на сырых данных, которые вы очистили, экспортировали, а затем использовали эту модель в веб-приложении. ## Упражнение - "запаковка" модели Теперь пришло время _запаковать_ вашу модель! Вы можете сделать это в несколько строк кода. После того как модель будет _запакована_, загрузите ее и протестируйте на примере массива данных, содержащего значения для секунд, широты и долготы. ```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. Начните с создания папки **web-app** рядом с файлом _notebook.ipynb_, где находится ваш файл _ufo-model.pkl_. 1. В этой папке создайте еще три папки: **static**, с папкой **css** внутри нее, и **templates**. Теперь у вас должны быть следующие файлы и директории: ```output web-app/ static/ css/ templates/ notebook.ipynb ufo-model.pkl ``` ✅ Обратитесь к папке с решением, чтобы увидеть готовое приложение 1. Первый файл, который нужно создать в папке _web-app_, это файл **requirements.txt**. Как _package.json_ в приложении на JavaScript, этот файл перечисляет зависимости, необходимые для приложения. В **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. Создайте **index.html** в папке _templates_. 3. Создайте **styles.css** в папке _static/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 🛸 UFO Appearance Prediction! 👽

According to the number of seconds, latitude and longitude, which country is likely to have reported seeing a UFO?

{{ prediction_text }}

``` Обратите внимание на шаблонизацию в этом файле. Заметьте синтаксис "усиков" вокруг переменных, которые будут предоставлены приложением, например текст предсказания: `{{}}`. Также есть форма, которая отправляет предсказание на маршрут `/predict`. Наконец, вы готовы создать Python файл, который управляет использованием модели и отображением предсказаний: 1. В `app.py` добавьте: ```python 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_text="Likely country: {}".format(countries[output]) ) if __name__ == "__main__": app.run(debug=True) ``` > 💡 Совет: когда вы добавляете [`debug=True`](https://www.askpython.com/python-modules/flask/flask-debug-mode) при запуске веб-приложения с использованием Flask, любые изменения, которые вы вносите в приложение, будут отражены немедленно без необходимости перезапуска сервера. Будьте осторожны! Не включайте этот режим в производственном приложении. Если вы выполните `python app.py` или `python3 app.py`, ваш веб-сервер запустится локально, и вы сможете заполнить короткую форму, чтобы получить ответ на ваш вопрос о том, где были замечены НЛО! Прежде чем это сделать, взгляните на части `app.py`: 1. Сначала загружаются зависимости и запускается приложение. 1. Затем импортируется модель. 1. Затем на домашнем маршруте отображается index.html. На маршруте `/predict` происходит несколько вещей, когда форма отправляется: 1. Переменные формы собираются и преобразуются в массив numpy. Затем они отправляются в модель, и возвращается предсказание. 2. Страны, которые мы хотим отображать, преобразуются в читаемый текст из их предсказанного кода страны, и это значение отправляется обратно в index.html для отображения в шаблоне. Использование модели таким образом, с Flask и запакованной моделью, относительно просто. Самое сложное — понять, в каком формате должны быть данные, которые нужно отправить в модель, чтобы получить предсказание. Это полностью зависит от того, как была обучена модель. В данном случае нужно ввести три точки данных, чтобы получить предсказание. В профессиональной среде вы можете понять, насколько важна хорошая коммуникация между людьми, которые обучают модель, и теми, кто использует ее в веб- или мобильном приложении. В нашем случае это только один человек — вы! --- ## 🚀 Задание Вместо работы в ноутбуке и импорта модели в приложение Flask, вы могли бы обучить модель прямо внутри приложения Flask! Попробуйте преобразовать ваш код Python из ноутбука, возможно, после очистки данных, чтобы обучить модель внутри приложения на маршруте `train`. Какие плюсы и минусы у такого подхода? ## [Тест после лекции](https://ff-quizzes.netlify.app/en/ml/) ## Обзор и самостоятельное изучение Существует множество способов создания веб-приложений для использования моделей машинного обучения. Составьте список способов, которыми можно использовать JavaScript или Python для создания веб-приложения с использованием машинного обучения. Учитывайте архитектуру: должна ли модель оставаться в приложении или находиться в облаке? Если последнее, то как вы будете к ней обращаться? Нарисуйте архитектурную модель для прикладного ML веб-решения. ## Задание [Попробуйте другую модель](assignment.md) --- **Отказ от ответственности**: Этот документ был переведен с помощью сервиса автоматического перевода [Co-op Translator](https://github.com/Azure/co-op-translator). Несмотря на наши усилия обеспечить точность, автоматические переводы могут содержать ошибки или неточности. Оригинальный документ на его исходном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или неправильные интерпретации, возникшие в результате использования данного перевода.