Това е втората част от моето пътуване за „изграждане на система, която минимизира количеството имейли за продажби“, с които се занимавам всеки ден. За да обобщим, системата се свързва с Gmail на потребителя чрез OAuth, определя дали входящият имейл е от представител за развитие на продажбите (from_SDR=1) и премества тези имейли в специална папка за „Прочетете по-късно“. Ако имейлът не е from_SDR, той оставя класифицирания имейл в основната входяща кутия.

В „последната ми публикация“ извлякох етикетирани имейли от входящата си кутия, обучих модел за машинно обучение да класифицира дали имейлите идват от SDR и оцених ефективността на модела. Тук описвам как внедрих модела си в крайна точка на API, за да мога да го извикам от аплет на Gmail.

Има много рецепти за пренасяне на вашия модел в облака. Намерих този пример от AWS, „Bring Your Own Sci-kit Model“, за най-простия, най-добре обяснен и най-приложим към моя проект. Стъпките по-долу показват как контейнеризирах моя модел, избутах този контейнер в сървър на Sagemaker и след това използвах Chalice за управление на крайна точка на API към този сървър.

Настройване на My Docker контейнер

Docker предоставя начин за пакетиране на код в изображение, което може да се изпълнява на сървър като самостоятелна среда. Dockerfile указва как трябва да бъде създадено изображението. В този случай направих Docker изображение, което може да изпълнява Python 3.7.7, за да съответства на моята локална среда и да импортирам необходимите пакети за изпълнение на моя скрипт за обучение, описан в част първа.

Ако следвате този пример на AWS, обърнете внимание на тези важни актуализации, необходими, за да работи с Python 3: (i) Надстроих до Python 3.7.7 в ред 3, което (ii) промени местоположението на пакетите в ред 17.

Копирах контейнерната директория от примера на AWS, който предоставя необходимите файлове за пакетиране на алгоритъм за Amazon SageMager. Например тази директория включва шел код за изграждане и изпращане на изображението на контейнера към AWS ECR с помощта на docker push. Имайте предвид, че промених примерния код, за да работи с AWS CLI v2 (вижте редове 45–50):

Но преди да успея да създам и насоча към AWS ECR, трябваше да подготвя файловете в директорията на контейнера, които изпълняват стъпките за обучение и прогнозиране.

Добавяне на моя скрипт за обучение към контейнера

Замених файла train в примерния контейнер с моя собствен скрипт за обучение (вижте първа част от тази серия за подробности относно това):

Обърнете внимание на двата импортирани модула от preprocess.py, които трансформират данните във формат, приемлив за моя модел на машинно обучение. Тези класове и функции са включени в същата папка:

И накрая, промених файла predictor.py в примерния контейнер, както следва:

Промените ми са отразени най-вече в редове 64–78, където актуализирах примера на AWS, за да използвам най-новата версия на StringIO и включвам заглавки в рамката с данни data, за да съответства на очаквания вход на моя модел.

След като редактирах тези файлове, изпълних скрипта за изграждане и натискане:

$ sh build_and_push.sh sg_linearsvm

който създаде контейнера на Docker и го избута към AWS ECR.

Тествам алгоритъма си на localhost, преди да го внедря

Преди да внедрите модела, полезно е да определите дали контейнеризираният код работи правилно. Примерът на AWS предоставя поддиректория local_test за тази цел. Клонирах това репо и добавих моите примерни данни за обучение в съответната папка /local_test/test_dir/input/data/training и след това изпълних:

$ ./train_local.sh sg_linearsvm

Този скрипт на обвивката изпълнява докер изображението в режим train:

image=$1
mkdir -p test_dir/model
mkdir -p test_dir/output
rm test_dir/model/*
rm test_dir/output/*
docker run -v $(pwd)/test_dir:/opt/ml --rm ${image} train

Използвайки версията local_test на моя контейнер, успях да диагностицирам и разреша различни проблеми, свързани с пренасянето на моя скрипт от Google Colab към контейнера на Docker. След като тези проблеми бяха решени, трябваше да тествам и функционалността на serve. Така че изтичах:

./serve_local.sh sg_linearsvm

който е shell скрипт, който изпълнява следния код:

image=$1
docker run -v $(pwd)/test_dir:/opt/ml -p 8080:8080 --rm ${image} serve

След като Docker сървърът стартира локалното изображение, успях да получа прогноза от моя терминален команден ред:

./predict.sh payload.csv text/csv

където payload.csv беше CSV файл, който имитира очаквания вход на модела:

Ето отговора, който показва, че този контейнер се държи по предназначение:

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

Разполагане на My Container в Amazon SageMaker

Първо, настроих средата, като посочих кофа S3 и роля на SageMaker. Също така създадох sess, за да запомня параметрите на връзката, които използвах за извършване на различни операции на SageMaker.

След това посочих къде моделът трябва да намери моите данни за обучение в S3 (редове 1–3) и идентифицирах image с помощта на подходящия акаунт, регион и имена на контейнери (редове 5–11).

За да пасна на моя алгоритъм, създадох оценител на SageMaker, който определя как да използвам контейнера за обучение (редове 1–4 по-долу). След това използвах .fit на estimator, за да тренирам спрямо данните, които качих в data_location (ред 6 по-долу).

Внедряването на модела в хостинга на SageMaker изискваше повикване за внедряване на монтирания модел (ред 9 по-горе). Това извикване взема брой екземпляри, тип екземпляр и по избор функции за сериализиране и десериализиране.

С това имах обучен модел за получаване на прогнози в реално време. В следващия раздел описвам как да изложа уеб достъпна API крайна точка.

Направете модела достъпен чрез API

За този проект избрах AWS Chalice за създаване и внедряване на приложения с помощта на Amazon API Gateway и AWS Lambda. Извън кутията, той осигурява:

• Инструмент за команден ред за създаване, внедряване и управление на вашето приложение
• Познат и лесен за използване API за деклариране на изгледи в код на Python
• Автоматично генериране на правила за IAM

От командния ред изпълних:

$ chalice new-project sg_to_api

След това отидох до тази папка и редактирах файла app.py, който дефинира изгледите и произтичащата логика. Ето как конфигурирах своя API:

Хващам входяща заявка и я декодирам (редове 24–25). След това преминавам през данните, за да изградя речник (ред 27–36), който въвеждам в рамка с данни на Pandas (редове 38–39), за да мога да преформатирам текста в хубав CSV полезен товар (ред 40). След това, в редове 46–51, извиквам sagemaker.invoke_endpoint(), препращайки към името на крайната точка в предходния раздел на тази публикация. Накрая резултатът се съхранява и предава като HTML отговор (редове 53–92), така че мога да демонстрирам това от уеб браузър.

За да разположа това приложение, отидох до директорията sg_to_api и стартирах chalice deploy:

$ chalice deploy
...
Initiating first time deployment...
https://xyz123.execute-api.us-east-1.amazonaws.com/api/

Това е. Имах работещ API с помощта на API Gateway и Lambda.

(Харесва ми, че мога да актуализирам файла app.py и след това бързо да преразпределя промените в API, като стартирам chalice deploy отново.)

Тестване на крайната ми точка на API в природата

Въпреки че можех да използвам моя API с помощта на curl, нямах търпение да покажа това на някои нетехнически приятели, които не биха се чувствали комфортно да използват команден ред. За тях хоствах статична уеб страница, използвайки S3, която приема въвеждане на текст и прави POST заявка до моята крайна точка и извежда HTML отговора от app.py.

Първо създадох кофа S3:

$ aws s3api create-bucket --bucket sg-learner-test-1 --region us-east-1

След това конфигурирах моята кофа да поддържа хостинг на статичен уебсайт:

$ aws s3 website s3://sg-learner-test-1/ --index-document index.html --error-document error.html

Накрая създадох файл index.html, който копирах в моя S3 контейнер с глобални разрешения за достъп:

$ aws s3 cp index.html s3://sg-learner-test-1/index.html --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers

Заради този пример не прекарах никакво време в разкрасяване на уеб страницата - моля, имайте отношение към нейната грозота:

След като натиснах този код, разрових входящата си кутия и поставих имейли в частта „Тяло на имейла“ на уеб страницата. Ако никога не съм изпращал имейл на подателя, тогава съм направил полето „Студен контакт“ = 1, в противен случай въвеждам 0.

Виждането на резултатите беше като магия! И въпреки че бих се радвал да предоставя крайната точка тук, за да можете сами да тествате модела, хостването на крайната точка на SageMaker струва $0,28 на час (~$201 на месец), което е малко богато, ако искате да играете с него 😉

Вместо това записах няколко примера за вас:

(Чудите ли се защо има ham в анимацията по-горе? Просто: ham е по-бърз начин за етикетиране на имейл, който „не е спам.“

Бъдещи насоки

Следващата стъпка в моето приключение е да пропусна интерфейса на уеб страницата и да извикам моята крайна точка на API от друго приложение. Повече за това скоро!

Има твърде много хора, на които да благодарим, че направиха тази публикация възможна. Ето няколко човека, които значително насочиха моето пътуване: Куин Ланърс (за разгръщане на Scikit-Learn Model в AWS), Леон Геритсен (за създаване на REST API с чаша), Патрик Микелбергер (относно внедряването на безсървърна ML микроуслуга) и «Дейвид Арпин, Том Фаулхабер и др. (относно изграждане на ваш собствен контейнер за алгоритъм).