Создайте и разверните простое приложение Flask для своего проекта машинного обучения.

Цель этой статьи - показать вам очень простую «производственную» модель машинного обучения с использованием Flask, Heroku и GitHub. В этой статье предполагается, что вы хорошо разбираетесь в коде Python и что вы уже обучили модель машинного обучения на Python, но ранее не создавали приложение Flask для этой цели. Позже вам понадобится доступ к GitHub и учетная запись Heroku; мы будем создавать репозиторий для нашего приложения и развертывать его на Heroku через репо. Приятно иметь опыт работы с HTML и Jinja, но это не обязательно.

Flask - это легкий фреймворк для веб-приложений, который довольно прост в использовании и хорошо документирован. Также несколько тривиально запустить его на облачной платформе, такой как Heroku.

Недавно я сделал приложение Flask для одной из своих моделей. Я построил модель CNN для прогнозирования исходов пневмонии с помощью рентгена грудной клетки и хотел предоставить интерактивную предварительную модель для нетехнической презентации. Это может быть сложно сделать с помощью IDE и записных книжек, поэтому я быстро сделал приложение Flask в качестве «доказательства концепции», демонстрирующей мою модель, делающую прогнозы.

Моя модель в действии

Прежде чем мы начнем, вы можете взглянуть на приложение, которое я сделал с помощью того же метода, чтобы дать вам представление о том, что мы делаем. Набор данных, который я использовал для своего проекта, был получен с сайта kaggle.com по ссылке ниже.



Приложение My Flask размещено на Heroku. Модель представляет собой модель CNN h5 в керасе, но почти любая модель ML будет работать таким же образом. Если вы можете выполнить model.predict (), у вас будет достаточно для создания приложения для прогнозирования.

Не стесняйтесь посетить приложение и загрузить рентгеновские снимки грудной клетки (jpg или png) и предсказать, нормальные они или пневмония. Вы можете использовать изображения из набора данных для ввода в модель или попробовать свои собственные.

А теперь давайте вместе сделаем "простое" приложение.

Шаг 1. Создайте структуру папки Flask

Начнем с создания виртуальной среды для нашего проекта (я рекомендую использовать Python 3.7). Используйте обычный рабочий процесс для отправки проекта на GitHub. Если мы сохраним организованный репозиторий, потом будет легко развернуть его на Heroku через Github.

Ниже представлена ​​удобная для новичков структура приложения, которую я использую для студентов. Более сложные приложения могут потребовать более сложной структуры. Прежде чем начать, найдите время, чтобы создать структуру папок. Это отличный способ визуализировать свой проект, прежде чем писать код. Подробнее о структуре папок Flask можно прочитать здесь.

My Project/
├── app.py
├── requirements.txt
├── Procfile
├── templates/
│   └── main.html
├── static/
│   ├── images/
│   ├── stylesheets/
│   └── fonts/
├── model/
│   └── my_model.pkl

Шаг 2. Создайте простое приложение Flask

Начните с установки библиотеки Flask в ваш venv. Инструкции по установке и настройке на веб-сайте Flask помогут вам начать работу. Очень важно обратиться к веб-сайту Flask, чтобы избежать неприятностей, если вы не уверены в каких-либо действиях.

А пока мы начнем с приложения Hello World Flask. Я просто создам файл с именем app.py (в корне моей структуры папок, как показано на шаге 1). Вставьте следующий код в app.py.

Это был код Flask «Hello World». Он импортирует класс Flask, создает объект Flask с именем app и определяет маршрут, который возвращает «Hello, World!». Чтобы запустить приложение Flask, просто перейдите в папку «Мой проект» в своем интерфейсе командной строки и введите

% flask run

Это запускает встроенный сервер, которого достаточно для разработки и устранения неполадок, но не того, что вы использовали бы в производственной среде. Перейдите в местоположение приложения по умолчанию http://127.0.0.1:5000/ в своем браузере, и вы должны увидеть свое сообщение.

Что это за код над моей функцией?

Мы делаем веб-приложение. Все делается через маршруты во Flask. По сути, вы сопоставляете URL-адреса с действиями. Когда вы начинаете использовать Flask, больше всего может сбить с толку следующая строка.

@app.route(‘/’)

Символ @ - это просто декоратор Python. Декоратор - это довольно непонятная часть синтаксического сахара в Python. Он изменяет функции; более конкретно, это функция , которая принимает другую функцию в качестве параметра и возвращает другую функцию. Если это сбивает с толку ... Я с вами согласен. К счастью, нам не нужно полностью понимать это, чтобы использовать.

Что нам необходимо знать: декоратор связывает относительный URL-адрес (маршрут) в нашем приложении с функцией, которую он украшает. Это означает, что функция hello_world связана с маршрутом (‘/’), который является корнем нашего веб-приложения.

Когда мы запускаем приложение, мы посещаем корневой URL, который «запускает» функцию hello_world, даже не вызывая ее специально. Функция hello_world возвращает сообщение по маршруту, и мы видим, как оно волшебным образом появляется на нашем сервере по корневому URL-адресу.

Иногда URL-адреса маршрутизации для достижения интерактивности могут сбивать с толку и быть громоздкими. В другой раз вы можете увидеть абсолютный гений всего этого.

Шаг 3. Загрузите модель

Мы создали папку в нашей файловой структуре для хранения нашей модели. В зависимости от типа изготовленной вами модели существуют разные способы ее хранения. Возможно, самый простой способ - использовать рассол. Pickling - это просто сериализация объекта в Python для последующего использования. Травление сохраняет объект Python в его текущем состоянии.

Допустим, вы создали модель линейной регрессии в сеансе кодирования с именем объекта LR_model. Чтобы обработать ее, просто выполните следующие действия:

import pickle
with open("my_model.pkl", 'wb') as file:  
    pickle.dump(LR_model, file)

В текущем каталоге появится новый файл под названием my_model.pkl. Это файл, который помещается в папку с именем модель, показанную в структуре папок Шага 1. В app.py мы можем отменить травление и получить модель, используя следующее.

import pickle
with open('model/my_model.pkl', 'rb') as file:  
    model = pickle.load(file)

Давайте продолжим и интегрируем это в наше приложение. Поместив нашу маринованную модель в структуру папок, мы можем открыть ее и сделать прогнозы, которые затем можно будет вывести в корень нашего приложения Flask.

В этой гипотетической модели модель принимает массив длиной 3, делает прогноз и возвращает этот прогноз пользователю в виде строки.

Что мы изменили:

  • Добавлены строки 2, 3, 4, 6, 7 и 13.
  • Параметр def hello_world изменен на def index
  • Вернуть предсказание pred (в виде строки) вместо просто «hello world».
  • Добавлен в строки 16–17, потому что это хорошая практика.

Шаг 4. Добавьте шаблон

Это было здорово, но нам нужно немного больше, чем просто число на веб-странице. У Flask есть отличный инструмент, позволяющий упростить сложные веб-интерфейсы. Давайте посмотрим, как использовать шаблон Flask.

Если вы знакомы с HTML (и CSS), вы почувствуете себя как дома в этой части. Нам нужно сделать HTML-страницу. Я назову свой index.html и помещу его в папку templates (расположение по умолчанию для шаблонов). Эта страница будет моей новой "домашней страницей" для моего веб-приложения. В файл index.html я помещаю следующий код:

Для доступа к моему шаблону в flask есть функция под названием render_template, которая может «визуализировать» html-файл, хранящийся в папке шаблонов. Когда вы возвращаете render_template из функции, он будет доступен по указанному маршруту / URL-адресу (указанному в декораторе) для функции. В приведенном ниже коде index.html доступен в корневой папке.

Что мы изменили:

  • Добавлена ​​функция render_template для импорта
  • Изменена строка 14 для возврата вызова функции render_template.

После установки обоих файлов команда flask run должна вызвать шаблон html.

Теперь мы можем видеть веб-страницу, но мы также хотели бы иметь возможность отображать прогноз в шаблоне. Для этого мы меняем всего две строчки кода. Сначала измените функцию render_template, чтобы включить аргумент ключевого слова для каждого значения, которое вы хотите использовать в шаблоне. Эти значения будут доступны для отображения или изменения на веб-странице. На данный момент мы просто отправим одно значение pred в виде строки.

Что мы изменили:

  • добавил kwarg в нашу функцию render_template (строка 4 выше)

Теперь переключитесь на свой шаблон index.html. Мы добавим немного нотации шаблона Jinja в наш html. Jinja - это язык шаблонов для интеграции кода Python в наши HTML-страницы. Самая простая реализация показана ниже. При запуске приложение flask должно теперь отображать переданную переменную pred.

Что мы изменили:

  • Единственное, что изменилось, - это строка 8. Нотация {{}} Jinja позволяет отображать переданную "переменную" с тем же именем, отправленную из функции render_template в любом месте внутри HTML.

Jinja может сделать для нас еще много работы, и я рекомендую вам проверить это. Мы можем реализовать Python-подобные структуры, такие как циклы и условия, непосредственно внутри нашего HTML-шаблона, а также динамически реализовать многие функции форматирования.

Шаг 5. Используйте веб-форму для публикации ввода для вашей модели

Это веб-приложение было бы не очень полезным, если бы мы не давали пользователю возможность вводить данные для прогнозирования. В моей собственной модели пользователь отправлял данные рентгеновского снимка. Для этой модели мы просто передадим несколько цифр.

Наша гипотетическая модель будет линейной регрессией, которая определяет цены на жилье. Мы отправим в эту простую модель количество кроватей, ванн и квадратные метры, чтобы спрогнозировать цену. Все данные будут отображаться на одной странице.

Мы добавим форму в наш HTML-шаблон.

Что мы изменили:

  • Добавлен тег формы в строке 8 (закрывается на строке 13). Указанный метод POST и тип кодирования для multipart / form-data.
  • В мою форму добавлены три числовых ввода в строках 9–11, которые будут запрашивать числовой ввод в поле.
  • Добавлена ​​кнопка отправки в строке 12

Здесь мы используем тег ‹form›, чтобы содержать элементы пользовательского ввода. В атрибутах ‹form› мы указываем здесь метод и тип кодировки. Важно, чтобы они оставались такими же, как показано. В форму мы добавили три числовых входа для желаемых характеристик дома и добавили кнопку отправки для POST (отправки) информации. Как написано в настоящее время, данные формы будут отправлены только после нажатия кнопки отправки.

Теперь переключитесь обратно на app.py, чтобы мы могли добавить механизм для приема этих отправленных значений в Python. Для тега ‹form› задано значение POST. Мы собираемся настроить наш метод маршрута для приема соответствующей информации POST. По умолчанию маршруты имеют только метод GET, если не указано иное.

Что мы изменили:

  • Строка 1 - Мы добавили объект запроса в импорт фляги для получения данных формы.
  • Строка 11 - Мы добавили POST в декоратор, чтобы разрешить отправку формы.
  • Строка 13 - Добавлен оператор if для проверки, было ли что-нибудь опубликовано. Если была публикация, мы берем данные и визуализируем шаблон. В противном случае мы визуализируем шаблон без него.
  • Строки с 14 по 15 - мы считываем значения из формы POST в python, используя объект запроса и нотацию, подобную словарю. Ключ, используемый для доступа к значению, такой же, как значение имени во входных данных формы в шаблоне.
  • Строка 17 - теперь мы используем опубликованные данные формы для загрузки модели и создания прогноза (который затем отправляется обратно на веб-страницу через возвращенный render_template)

Базовый функционал есть. Клиент вводил три числа, нажимал «Отправить» и видел результат.

Важный

  • Вы должны добавить несколько проверок для проверки данных вашей формы.
  • Вы должны дополнительно убедиться, что ваши входные данные для прогнозирования действительны для вашей модели, прежде чем запускать метод прогнозирования.
  • Убедитесь, что ваше приложение не дает сбоев при вводе различных форм.
  • Вы можете изучить использование Werkzeug на веб-сайте Flask для проверки входных данных формы, чтобы сделать ваше приложение более безопасным и предотвратить взлом.

Шаг 6. Создайте стиль

Я оставлю это на ваше усмотрение, так как он отнимает много времени и требует множества личных предпочтений для вашего приложения / модели. Вам не нужно полностью стилизовать его перед развертыванием такого приложения, и это действительно зависит от вашей аудитории и причины развертывания.

Статическая папка

Если вы добавляете файлы (изображения, таблицы стилей, сценарии, наборы данных и т. Д.) На свои веб-страницы / шаблоны, все эти ресурсы помещаются в статическую папку. Для этого есть статическая папка; вы можете обслуживать изображения, таблицы стилей и скрипты так же, как и любой веб-сайт. Считайте остальные папки недоступными для веб-дизайна.

Шаг 7. Подготовьте свое приложение для Heroku

Наша конечная цель - переместить наш проект в облако. Нам нужно добавить в наш проект два файла, чтобы сделать его удобным для сборки на Heroku.

requirements.txt

Этот файл попадает в ваш корень (см. Структуру папок). Это простой текстовый файл, в котором перечислены все ваши импортированные файлы. Когда вы создаете свое приложение, Heroku будет перебирать каждую строку в вашем файле requirements.txt, чтобы установить необходимые библиотеки для вашего приложения.

Ошибки в файле требований приводят к сбою приложения во время сборки. Устранение неполадок также чрезвычайно сложно, поэтому убедитесь, что все они указаны правильно.

Ниже приведен файл, который я использовал для своего проекта. Это импорт и конкретный номер версии каждой внешней библиотеки, которую я использовал.

Flask==1.1.2
Jinja2==2.11.2
keras
numpy==1.18.5
Werkzeug==1.0.1
requests
gunicorn
tensorflow==2.3.1
h5py==2.10
Pillow==8.0.1

Чтобы избежать неприятностей, просмотрите каждую строку и убедитесь, что вы можете выполнить установку pip для каждого требования к локальной виртуальной среде.

% pip install Flask==1.1.2

Выполнение этих команд pip - это то, что Heroku собирается делать. Если на вашем компьютере возник конфликт или вам необходимо удалить и переустановить разные версии, убедитесь, что вы указали правильную окончательную версию каждой библиотеки в requirements.txt.

Procfile

Создайте файл с именем Procfile и поместите его в корневой каталог, как показано в структуре папок в верхней части статьи. НЕ добавляйте расширение, чтобы сделать его Procfile.txt или что-то еще, это просто Procfile.

Procfile просто сообщает Heroku, как обрабатывать различные процессы для вашего проекта. Для наших просто поместите следующую строку в свой файл Procfile.

web: gunicorn app:app

Gunicorn - это сервер интерфейса шлюза веб-сервера (WSGI), используемый для управления нашим приложением. Название нашего приложения - app, поэтому, если вы назвали свой app.py чем-то другим, вам также придется изменить это здесь.

Github

Наконец, поместите весь контент в репозиторий github. Убедитесь, что в фиксацию добавлены Procfile и requirements.txt. Вы готовы к развертыванию. Heroku действительно хорошо работает с GitHub. Вам нужно будет дать Heroku разрешение на доступ к GitHub, но Heroku проведет вас через процесс с удобными подсказками для добавления аутентификации.

Шаг 8: Разверните приложение на Heroku

Создайте учетную запись и войдите в Heroku. Вы можете легко запустить подобное приложение с бесплатной учетной записью, но, конечно, у них есть обновления для платных учетных записей.

  1. Перейдите на панель инструментов Heroku.
  2. Нажмите кнопку «Создать» и создайте новое приложение.
  3. Дайте вашему приложению уникальное имя. Он должен быть уникальным для всего Heroku.
  4. Появляется новый экран. В поле «Метод развертывания» выберите «GitHub».

5. Найдите имя репозитория вашего приложения.

6. Я рекомендую включить автоматическое развертывание. Это означает, что каждый раз, когда вы отправляете основную ветку вашего проекта на GitHub, Heroku автоматически создает и повторно развертывает ваше приложение. Это реальная экономия времени.

Попробуйте свое приложение

Если ваша сборка прошла успешно, вы сможете открыть ссылку «Открыть приложение» на любом компьютере. Ваша модель развернута, и вы можете переслать ссылку пользователям.

Удачи!