РИСК ПО УМОЛЧАНИЮ ДЛЯ ДОМАШНЕГО КРЕДИТА - Практический пример непрерывного машинного обучения - ЧАСТЬ 3: Развертывание с использованием Flask на AWS EC2

«Никакая модель машинного обучения не имеет ценности, если она не используется в производственной среде» - Луиджи Патруно

Большинство проектов и моделей, созданных по всему миру студентами, практиками и исследователями, никогда не проходят мимо их локальных компьютеров или, скорее, их ноутбуков Jupyter. Если в области машинного обучения и есть одна концепция, которой больше всего недооценивают, то это, безусловно, развертывание и производство моделей.

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

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

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

Оглавление

  1. Предварительные условия
  2. Строительство трубопровода
  3. Создание веб-API с использованием Flask
  4. Удаленная настройка инстанса AWS и веб-приложения
  5. Конечные заметки
  6. использованная литература

1. Предварительные требования

В предыдущем сообщении в блоге мы завершили построение нашей окончательной модели, т. Е. Разработали функции, настроили гиперпараметры, сделали прогнозы и вычислили метрики. Пришло время использовать эту модель для прогнозирования входящих данных.

Прежде чем двигаться дальше, сначала нам нужно сохранить несколько файлов. О каких файлах мы на самом деле говорим? Скажем, например, как мы видели во время разработки функций, мы предсказали некоторые недостающие значения функций EXT_SOURCE, используя модель регрессии XGBoost. А что, если во время тестирования мы обнаружим точку данных, в которой отсутствует значение EXT_SOURCE функций? Нам понадобится эта модель регрессии для прогнозирования недостающих значений, и для этой цели нам нужно сохранить модель регрессии, которую мы обучили во время разработки функций.

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

Один из таких отличных способов сохранения переменных - использование модуля pickle.

Модуль pickle реализует двоичные протоколы для сериализации и десериализации структуры объекта Python. Обработка - это процесс, при котором иерархия объектов Python преобразуется в поток байтов, а извлечение - это обратная операция, посредством которой поток байтов (из двоичного файла или байтового объект ) преобразуется обратно в иерархию объектов.

- https://docs.python.org/3/library/pickle.html

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

Как только мы определили переменные, которые нам понадобятся для прогнозов во время тестирования, пора переходить к следующему шагу.

2. Строительство трубопровода

Теперь нам нужно создать конвейер, который может упростить весь процесс получения ввода и генерации вывода всего в одной строке кода, используя классы и функции.

Пожалуйста, обратите внимание, что, хотя лучшей моделью, которую мы получили в прошлом блоге, была модель XGBoost с 600 входными функциями, тем не менее, поскольку мы собираемся развернуть нашу модель на сервере с довольно низкими характеристиками (1 ГБ ОЗУ, одноядерный ), да, это то, что вы получаете бесплатно 😛, мы обучим модель LightGBM, которая намного быстрее, чем первая, только с 300 основными функциями. Блокнот для обучения модели можно найти в моем репозитории на GitHub - здесь.

Теперь, когда у нас есть окончательный набор функций и наша окончательная модель классификации, мы можем построить окончательный конвейер, как pipeline.py. Этот файл python содержит класс с именем final_pipeline, который содержит 4 функции-члена, а именно. __init__, load_required_files, preprocessing и predict. Нам не нужно объяснять, что будут делать эти функции, поскольку их названия говорят сами за себя.

Весь конвейер слишком длинный для этого сообщения в блоге, поэтому мы просто увидим вызов функции и вывод из Jupyter Notebook.

  • На изображении выше мы сначала загружаем таблицу данных тестирования, из которой мы будем использовать случайную точку данных для получения прогноза.
  • Затем мы создаем объект класса final_pipeline.

  • В первом блоке приведенного выше изображения сначала произвольно выберите точку тестовых данных из набора тестовых данных и отобразите ее в выходных данных.
  • Затем мы вызываем метод прогнозирования из нашего класса final_pipeline, который дает нам прогнозируемую вероятность класса и метку, где 0 обозначает не дефолт, а 1 означает дефолтер. Он также возвращает некоторые функции, значения которых могут использоваться для интерпретации предсказанной метки класса.

Давайте посмотрим, что на самом деле происходит внутри функции predict.

  • Из приведенного выше фрагмента кода мы видим, что эта функция создает соединение с базой данных, которая содержит данные о предыдущих займах заявителя, как мы видели в части EDA.
  • Затем он вызывает другую функцию из того же класса, то есть функцию preprocessing, которая предварительно обрабатывает данные до требуемого формата. После завершения предварительной обработки наши данные имеют формат, точно необходимый модели для прогнозирования.
  • Сначала мы делаем прогноз для каждой из 3-кратных моделей, которые мы обучили, а затем усредняем прогноз по этим складкам, чтобы получить окончательную предсказанную вероятность.
  • Теперь мы преобразуем эту вероятность в метку класса на основе оптимального порога, найденного на этапе обучения, и возвращаем предсказанную вероятность, метку класса вместе с некоторыми важными значениями характеристик.

Итак, мы увидели, что наш конвейер работает должным образом, то есть дает разумный вывод для каждого ввода без каких-либо ошибок. Следующий шаг - каким-то образом перенести эту структуру ввода-вывода в веб-среду, где пользователь может вводить ввод и получать вывод на веб-странице.

3. Создание веб-API с использованием Flask.

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

Flask в основном помогает создавать веб-API всего несколькими строками кода. Мы посмотрим на код для лучшего понимания.

Приведенного выше фрагмента кода достаточно для создания нашего полного веб-API (да, это так просто), хотя нам также необходимо разработать HTML-страницы, с которыми этот API будет взаимодействовать. Мы постараемся понять код построчно.

  • Во-первых, мы импортируем кучу библиотек. Мы также импортируем класс final_pipeline из pipeline.py, который мы видели выше.
  • Затем мы создаем экземпляр объекта Flask с именем переменной ‘app’, используя app = Flask(__name__). Здесь значение __name__ будет зависеть от способа доступа к этому файлу app.py. Если мы обращаемся к нему напрямую, он будет иметь значение, равное '__main__'. В последней строке кода мы также проверяем, был ли получен доступ к этому файлу python напрямую или нет, и если да, то мы запускаем это веб-приложение на основе Flask по URL-адресу localhost:5000.
  • Мы также создаем объект нашего final_pipeline класса с именем test_predictor_class.
  • Теперь мы открываем вспомогательный файл, который мы обсуждали ранее.
  • В нашем веб-приложении у нас есть три веб-страницы, а именно домашняя страница, страница прогнозов и страница результатов.
  • Если в конце URL есть только ‘/’, выполняется строка @app.route('/', methods = ['GET']), которая вызывает функцию home_page(). Здесь methods = ['GET'] указывает, что мы можем получить доступ к этой функции только через URL-адрес, а не через какую-либо другую веб-страницу. Эта функция возвращает обработанный HTML-шаблон с именем home-page.html.
  • В следующей строке у нас есть @app.route('/home', methods = ['POST','GET']). Эта строка кода подразумевает, что если URL-адрес содержит /home или действие /home было опубликовано какой-либо другой веб-страницей, вызывается функция inputs_page(). Эта функция отображает другой шаблон HTML с именем predict.html, который содержит форму, принимающую SK_ID_CURR в качестве входных данных. Здесь мы использовали the methods = ['POST','GET'], что означает, что эта строка может быть выполнена как если какая-то другая функция вызывает ее, так и если к ней обращаются через URL-адрес.
  • В следующей строке находится наша самая важная функция, то есть @app.route('/predict', methods = ['POST']). Эта строка кода подразумевает, что эта строка должна быть выполнена, если какая-либо другая веб-страница публикует /predict действие. Функция под ним, то есть функция prediction(), является наиболее полезной функцией во всем этом файле Python. Давайте посмотрим, что делает эта функция прогнозирования.
  1. Сначала мы создаем соединение с базой данных.
  2. Затем мы получаем SK_ID_CURR в качестве ввода от пользователя.
  3. Доступ к входным данным, полученным с веб-страницы, можно получить в формате JSON с помощью request.form. Преобразуем этот формат JSON в словарь и получаем значение, соответствующее ключу ‘SK_ID_CURR’.
  4. Затем мы приводим его к целочисленному типу данных и извлекаем соответствующую ему точку данных из базы данных.
  5. Затем мы вызываем функцию прогнозирования из нашего final_pipeline объекта test_predictor_class, который возвращает прогнозируемую вероятность, метку класса и важные значения характеристик.
  6. Наконец, функция prediction() отображает веб-страницу с именем result_and_inference.html и передает необходимые данные для печати на эту веб-страницу.
  7. Затем на этой веб-странице отображаются прогнозируемые результаты.

Структура папок

API Flask требует, чтобы данные были упорядочены в определенном формате, как показано выше. Все HTML-страницы должны перейти в папку templates, все изображения в static/images и файлы CSS в static/stylesheets.

HTML-страницы

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

а. home-page.html

Это код для файла home-page.html, который содержит только одну форму, которая в основном имеет кнопку отправки, которая используется для перенаправления на страницу predict.html путем взаимодействия с Flask API.

method = ‘POST’ и action = ‘/home’ информируют flask о необходимости вызова этой @app.route('/home', methods = ['POST','GET']) строки кода. Теперь все стало иметь смысл, не так ли?

б. Forex.html

Эта HTML-страница используется для получения SK_ID_CURR в качестве входных данных от пользователя через форму, значение которой находится между 100001 и 456255. Обратите внимание, что здесь мы не получаем фактическую статистику о кандидате от пользователя, поскольку имеется 120 необработанных функций. связанных со статистикой кандидата, и было бы обременительно создать такую ​​большую форму только ради практики. Таким образом, мы получаем только текущий идентификатор приложения от пользователя и извлекаем записи этого кандидата из базы данных SQL.

Опять же, как показано на изображении выше, строка action = '/predict' method = 'POST' сообщает flask о необходимости выполнения функции prediction().

c. result_and_inference.html

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

{% for table in tables %}
    {{ table|safe }}
{% endfor %}

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

Мы также отображаем прогнозируемую вероятность класса и метку класса, используя код:

Based on the model's prediction, the Client is <b><u>{{output_class}}</u></b> with a probability of <b><u>{{output_proba}}</u></b>

Доступ к веб-приложению

Чтобы получить доступ к этому веб-приложению, сначала запустите файл app.py напрямую. Теперь нам просто нужно перейти по URL-адресу, о котором мы говорили раньше, то есть localhost:5000/. Последние 3 веб-страницы будут выглядеть так, как показано на изображениях ниже.

Уф! Это было просто.

Теперь нам осталось только настроить экземпляр на AWS и развернуть там созданное выше веб-приложение. Чтобы все было легко для читателей, я создал отдельную папку с именем «Развертывание» в моем репозитории, которую вы можете загрузить напрямую и использовать.

Note: Из-за ограничения размера файла в GitHub нам не удалось загрузить файл базы данных в сам репозиторий. Базу данных можно скачать по ссылке на Google Диске - здесь. После загрузки этой базы данных просто вставьте ее в папку Final Pipeline Files.

4. Удаленная настройка экземпляра AWS и веб-приложения.

Я не смог бы пройти каждый этап настройки экземпляра AWS, но читатели могут пройти через эту ссылку, в которой есть полное пошаговое руководство по настройке экземпляра Free Tier EC2. .

После того, как мы создали экземпляр, это просто легкая прогулка.

а. Откройте командную строку / терминал.

б. Перейдите в папку, в которой мы сохранили наш key pair.pem файл, используя CD <directory path>.

c. Получите доступ к терминалу экземпляра EC2 с помощью команды SSH. Введите указанную ниже команду:

ssh -i "<key pair name>.pem" ubuntu@<Instance's Public IPv4 DNS>

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

d. Теперь, когда мы находимся в терминале экземпляра, нам сначала нужно установить Python и его зависимости, которые можно установить с помощью перечисленных ниже команд одну за другой.

sudo apt-get install python3-pip
pip install <each of the following packages>
Packages needed:
pandas
numpy
pickle-mixin
xgboost
lightgbm
flask

е. Теперь нам нужно скопировать всю папку с именем Deployment, которая содержит все файлы, обсуждаемые в этом посте, а также API, который мы создали, в этот экземпляр. Для этого мы сначала открываем другую командную строку / терминал и переходим в каталог, где у нас есть как файл key pair.pem, так и папка Deployment, содержащая файлы веб-API. Затем мы набираем указанную ниже команду:

scp -r -i "<key pair name>.pem" ./Deployment ubuntu@<Instance's Public IPv4 DNS>:~/

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

грамм. После того, как файлы были полностью скопированы на сервер EC2, мы возвращаемся к терминалу экземпляра EC2 и набираем ls. Теперь мы видим загруженную папку. Теперь мы переходим к этой папке с помощью cd Deployment.

час Теперь мы вводим указанную ниже команду, чтобы запустить наше веб-приложение на этом сервере.

nohup python3 app.py &

я. Это запустит веб-приложение на экземпляре EC2. Теперь, чтобы получить к нему удаленный доступ, все, что нам нужно сделать, это скопировать общедоступный IPv4 DNS нашего экземпляра и добавить в конце: 5000, и бум, мы получили вашу развернутую модель.

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

http://ec2-18-222-96-92.us-east-2.compute.amazonaws.com:5000/

Note: Только экземпляр t2.micro имеет право на бесплатный уровень, за все остальные экземпляры взимается плата. Не забудьте остановить экземпляр, когда закончите с ним.

5. Конец примечания

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

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

В случае каких-либо сомнений или вопросов читатели могут также оставить комментарий в самом сообщении блога или связаться со мной в LinkedIn.

Весь проект можно найти в моем репозитории GitHub по ссылке ниже.



использованная литература

  1. Pickle - сериализация объекта Python
  2. AWS EC2: создание экземпляра EC2 (Linux)
  3. Развертывание модели машинного обучения в Интернете с помощью Flask и Python.
  4. AppliedAICourse