РИСК ПО УМОЛЧАНИЮ ДЛЯ ДОМАШНЕГО КРЕДИТА - Практический пример непрерывного машинного обучения - ЧАСТЬ 3: Развертывание с использованием Flask на AWS EC2
«Никакая модель машинного обучения не имеет ценности, если она не используется в производственной среде» - Луиджи Патруно
Большинство проектов и моделей, созданных по всему миру студентами, практиками и исследователями, никогда не проходят мимо их локальных компьютеров или, скорее, их ноутбуков Jupyter. Если в области машинного обучения и есть одна концепция, которой больше всего недооценивают, то это, безусловно, развертывание и производство моделей.
Все мы отлично умеем моделировать машинное обучение. Мы можем знать все, от загрузки данных до очистки, анализа, разработки функций, моделирования, вывода и т. Д., Но когда дело доходит до реализации модели в реальном времени, большинство из нас остается пустым. Мы, как правило, не имеем ни малейшего представления о том, как поместить модель в среду реального времени, где для входящих входных данных нам придется продолжать генерировать выходные данные.
Но что на самом деле представляет собой развертывание и производство? Что ж, их не так уж и сложно понять. Машинное обучение используется для решения реальных проблем. Итак, что хорошего в решении проблемы, если оно не удовлетворяет своих конечных пользователей? Вот где возникают эти два термина. Внедрение модели в производство похоже на перенос неиспользованного спортивного оборудования, лежащего на складе, в настоящий тренажерный зал, где люди могут использовать его для тренировки. Таким образом, производство означает передачу модели машинного обучения потребителям, где они могут отправлять входные данные и получать прогнозируемые выходные данные.
В этом последнем блоге серии мы рассмотрим, как мы можем развернуть модель, построенную в предыдущем блоге, на сервере AWS, где любой человек из любой точки мира может получить прогнозы, созданные на основе нашей модели, без необходимости запускать нашу личную Блокнот Jupyter.
Оглавление
- Предварительные условия
- Строительство трубопровода
- Создание веб-API с использованием Flask
- Удаленная настройка инстанса AWS и веб-приложения
- Конечные заметки
- использованная литература
1. Предварительные требования
В предыдущем сообщении в блоге мы завершили построение нашей окончательной модели, т. Е. Разработали функции, настроили гиперпараметры, сделали прогнозы и вычислили метрики. Пришло время использовать эту модель для прогнозирования входящих данных.
Прежде чем двигаться дальше, сначала нам нужно сохранить несколько файлов. О каких файлах мы на самом деле говорим? Скажем, например, как мы видели во время разработки функций, мы предсказали некоторые недостающие значения функций EXT_SOURCE
, используя модель регрессии XGBoost. А что, если во время тестирования мы обнаружим точку данных, в которой отсутствует значение EXT_SOURCE
функций? Нам понадобится эта модель регрессии для прогнозирования недостающих значений, и для этой цели нам нужно сохранить модель регрессии, которую мы обучили во время разработки функций.
Таким образом, наша задача состоит в том, чтобы найти каждую переменную, модель, значения и т. Д., Которые мы использовали во время обучения и которые могут потребоваться для преобразования тестовых данных, чтобы привести их к требуемой форме и размеру. Нам также необходимо сохранить окончательную модель, которая нам понадобится для прогнозирования во время тестирования.
Один из таких отличных способов сохранения переменных - использование модуля pickle
.
Модуль
pickle
реализует двоичные протоколы для сериализации и десериализации структуры объекта Python. Обработка - это процесс, при котором иерархия объектов Python преобразуется в поток байтов, а извлечение - это обратная операция, посредством которой поток байтов (из двоичного файла или байтового объект ) преобразуется обратно в иерархию объектов.
Очень просто сохранить переменную в файле 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
в качестве входных данных. Здесь мы использовали themethods = ['POST','GET']
, что означает, что эта строка может быть выполнена как если какая-то другая функция вызывает ее, так и если к ней обращаются через URL-адрес. - В следующей строке находится наша самая важная функция, то есть
@app.route('/predict', methods = ['POST'])
. Эта строка кода подразумевает, что эта строка должна быть выполнена, если какая-либо другая веб-страница публикует/predict
действие. Функция под ним, то есть функцияprediction()
, является наиболее полезной функцией во всем этом файле Python. Давайте посмотрим, что делает эта функция прогнозирования.
- Сначала мы создаем соединение с базой данных.
- Затем мы получаем
SK_ID_CURR
в качестве ввода от пользователя. - Доступ к входным данным, полученным с веб-страницы, можно получить в формате JSON с помощью
request.form
. Преобразуем этот формат JSON в словарь и получаем значение, соответствующее ключу‘SK_ID_CURR’
. - Затем мы приводим его к целочисленному типу данных и извлекаем соответствующую ему точку данных из базы данных.
- Затем мы вызываем функцию прогнозирования из нашего
final_pipeline
объектаtest_predictor_class
, который возвращает прогнозируемую вероятность, метку класса и важные значения характеристик. - Наконец, функция
prediction()
отображает веб-страницу с именемresult_and_inference.html
и передает необходимые данные для печати на эту веб-страницу. - Затем на этой веб-странице отображаются прогнозируемые результаты.
Структура папок
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 по ссылке ниже.