Пошаговое руководство с примерами кода
Многие специалисты по данным, работающие с AWS, используют хостинг Amazon SageMaker для развертывания своих моделей машинного обучения. Однако на практике большинство решений машинного обучения начинаются с простых бизнес-правил (например, операторов if/then), а не сложных моделей машинного обучения. В этой статье я покажу, как развернуть простые бизнес-правила в SageMaker, чтобы специалисты по данным могли быстро вывести первоначальные бизнес-правила на рынок, прежде чем приступать к созданию более сложных моделей машинного обучения, не беспокоясь о создании совершенно новой модели. структура развертывания позже.
Во-первых, конечно, вам понадобится доступ к Amazon SageMaker. Запустите среду SageMaker Studio и создайте новую записную книжку с ядром Python 3 (Data Science) по умолчанию.
Теперь вы должны попасть в записную книжку Untitled.ipynb. Не стесняйтесь переименовывать его во что угодно.
Затем загрузите container.zip
из этого репозитория GitHub на свой локальный компьютер и загрузите его в свою среду SageMaker, щелкнув стрелку вверх в разделе навигатора файлов в левой части экрана. Не стесняйтесь клонировать репозиторий непосредственно в среду SageMaker, если у вас настроено подключение к GitHub.
Теперь вернемся к блокноту, который мы создали ранее, давайте сначала установим и загрузим соответствующие пакеты:
# Install and Load Packages !pip install -q sagemaker-studio-image-build import pandas as pd import numpy as np import sagemaker as sage import boto3 import re import os from sklearn.datasets import load_iris from sagemaker import get_execution_role from sagemaker.serializers import CSVSerializer
Далее, давайте импортируем некоторые образцы данных. Мы будем использовать классический набор данных Iris из scikit-learn.
# Data Preparation data = load_iris() df = pd.DataFrame(data=data.data, columns=data.feature_names) df.insert(loc=0, column='target', value=data.target) mapping = {0:'setosa', 1:'versicolor', 2:'virginica'} df['target'] = df['target'].map(mapping) df.head()
Сохраните полученный набор данных в файле CSV в папке data
.
os.makedirs('data', exist_ok=True) df.to_csv('data/iris.csv', header=False, index=False)
Теперь давайте разархивируем файл container.zip, который мы загрузили ранее:
# Unzip Deployment Package # Run the following conda install in case unzip is not found # !conda install -y -c conda-forge unzip !unzip container.zip
Не стесняйтесь просматривать файлы в папке container
и знакомиться. README.md
в папке содержит подробную документацию по каждому сценарию, поэтому мы не будем рассматривать ее все здесь. На высоком уровне этот контейнер изначально был разработан для обучения и размещения простой модели дерева решений, и я внес в него некоторые незначительные изменения, чтобы вместо размещения модели дерева решений в нем размещались некоторые произвольные правила. Для нашей цели container/model/predictor.py
— это единственный файл, который нам нужно изменить, поэтому давайте посмотрим на него:
# This is the file that implements a flask server to do inferences. It's the file that you will modify to # implement the scoring for your own algorithm. from __future__ import print_function import os import json import pickle import StringIO import sys import signal import traceback import flask import pandas as pd prefix = '/opt/ml/' model_path = os.path.join(prefix, 'model') # A singleton for holding the model. This simply loads the model and holds it. # It has a predict function that does a prediction based on the model and the input data. class ScoringService(object): model = None # Where we keep the model when it's loaded @classmethod def get_model(cls): """Get the model object for this instance, loading it if it's not already loaded.""" if cls.model == None: with open(os.path.join(model_path, 'decision-tree-model.pkl'), 'r') as inp: cls.model = pickle.load(inp) return cls.model @classmethod def predict(cls, input): """For the input, do the predictions and return them. Args: input (a pandas dataframe): The data on which to do the predictions. There will be one prediction per row in the dataframe""" clf = cls.get_model() return clf.predict(input) # The flask app for serving predictions app = flask.Flask(__name__) @app.route('/ping', methods=['GET']) def ping(): """Determine if the container is working and healthy. In this sample container, we declare it healthy if we can load the model successfully.""" health = ScoringService.get_model() is not None # You can insert a health check here status = 200 if health else 404 return flask.Response(response='\n', status=status, mimetype='application/json') @app.route('/invocations', methods=['POST']) def transformation(): """Do an inference on a single batch of data. In this sample server, we take data as CSV, convert it to a pandas data frame for internal use and then convert the predictions back to CSV (which really just means one prediction per line, since there's a single column. """ data = None # Convert from CSV to pandas if flask.request.content_type == 'text/csv': data = flask.request.data.decode('utf-8') s = StringIO.StringIO(data) data = pd.read_csv(s, header=None) else: return flask.Response(response='This predictor only supports CSV data', status=415, mimetype='text/plain') print('Invoked with {} records'.format(data.shape[0])) # Do the prediction # predictions = ScoringService.predict(data) # Model predictions predictions = np.where(data.iloc[:,0] > 7, 'a', np.where((data.iloc[:,0] <= 7) & (data.iloc[:,1] <= 3), 'b', 'c')) # Simple rule predictions # Convert from numpy back to CSV out = StringIO.StringIO() pd.DataFrame({'results':predictions}).to_csv(out, header=False, index=False) result = out.getvalue() return flask.Response(response=result, status=200, mimetype='text/csv')
Этот файл содержит класс ScoringService
, функцию здоровья ping
и функцию transformation
. Предсказание происходит внутри функции transformation
. Увеличим немного:
# Do the prediction # predictions = ScoringService.predict(data) # Model predictions predictions = np.where(data.iloc[:,0] > 7, 'a', np.where((data.iloc[:,0] <= 7) & (data.iloc[:,1] <= 3), 'b', 'c')) # Simple rule predictions
Поэтому, если вы действительно хотите делать прогнозы на основе модели дерева решений, обученной ранее в этом контейнере, вы должны разрешить predictions = ScoringService.predict(data)
. Однако, если вы хотите разместить некоторые произвольные правила, вы можете назначить набор логических операторов переменной predictions
. В этом примере я использовал функцию np.where()
из numpy для реализации своих логических операторов, а именно:
- Если первый столбец в моих входных данных (длина чашелистика) больше 7, то output=’a’
- В противном случае, если первый столбец меньше или равен 7, а второй столбец (ширина чашелистика) меньше или равен 3, тогда output=’b’
- В противном случае вывод = 'c'
Не стесняйтесь придумывать другой набор правил и вносить некоторые изменения в этот раздел кода. Сохраните файл после того, как вы закончите свои изменения.
Теперь, когда мы завершили настройку нашего образа докера (довольно просто, верно?), мы можем приступить к его созданию и сохранению в Amazon ECR (Elastic Container Registry). Начнем с некоторых модификаций разрешений:
- Прикрепите политику доверия к роли IAM выполнения SageMaker для AWS CodeBuild. Это гарантирует, что в дополнение к Amazon SageMaker AWS CodeBuild также может взять на себя эту роль, чтобы автоматизировать создание образов Docker.
- Перейдите в SageMaker Studio, затем щелкните свое «Имя пользователя».
- Скопируйте имя роли исполнения (не полный ARN)
- Перейдите на страницу службы IAM, затем нажмите «Роли», затем найдите роли по имени роли исполнения, которую вы скопировали выше, затем нажмите на единственный элемент, который отображается в разделе «Имя роли».
- Перейдите на вкладку «Доверительные отношения» и нажмите «Изменить политику доверия», затем скопируйте и вставьте следующий код в редактор и нажмите «Обновить политику» внизу страницы.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "sagemaker.amazonaws.com" }, "Action": "sts:AssumeRole" }, { "Effect": "Allow", "Principal": { "Service": "codebuild.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
2. Прикрепите дополнительную IAM-политику к исполнительной роли SageMaker, чтобы позволить ей создавать образ докера с помощью AWS CodeBuild.
- Щелкните вкладку «Разрешения» в роли исполнения SageMaker, затем выберите параметр «Создать встроенную политику» в раскрывающемся меню «Добавить разрешения».
- На странице «Создать политику» щелкните вкладку «JSON», затем скопируйте и вставьте следующий код в текстовую область, заменив текст по умолчанию, затем нажмите «Просмотреть политику». Выполните оставшиеся шаги, чтобы создать встроенную политику (не стесняйтесь называть ее как хотите).
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "codebuild:DeleteProject", "codebuild:CreateProject", "codebuild:BatchGetBuilds", "codebuild:StartBuild" ], "Resource": "arn:aws:codebuild:*:*:project/sagemaker-studio*" }, { "Effect": "Allow", "Action": "logs:CreateLogStream", "Resource": "arn:aws:logs:*:*:log-group:/aws/codebuild/sagemaker-studio*" }, { "Effect": "Allow", "Action": [ "logs:GetLogEvents", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:log-group:/aws/codebuild/sagemaker-studio*:log-stream:*" }, { "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "*" }, { "Effect": "Allow", "Action": [ "ecr:CreateRepository", "ecr:BatchGetImage", "ecr:CompleteLayerUpload", "ecr:DescribeImages", "ecr:DescribeRepositories", "ecr:UploadLayerPart", "ecr:ListImages", "ecr:InitiateLayerUpload", "ecr:BatchCheckLayerAvailability", "ecr:PutImage" ], "Resource": "arn:aws:ecr:*:*:repository/sagemaker-studio*" }, { "Effect": "Allow", "Action": "ecr:GetAuthorizationToken", "Resource": "*" }, { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:DeleteObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::sagemaker-*/*" }, { "Effect": "Allow", "Action": [ "s3:CreateBucket" ], "Resource": "arn:aws:s3:::sagemaker*" }, { "Effect": "Allow", "Action": [ "iam:GetRole", "iam:ListRoles" ], "Resource": "*" }, { "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::*:role/*", "Condition": { "StringLikeIfExists": { "iam:PassedToService": "codebuild.amazonaws.com" } } } ] }
Теперь вернемся к нашей записной книжке SageMaker Studio. Запустите следующий код в новом блоке ячеек, чтобы инициировать сборку докера. Обратите внимание, что это займет пару минут. Если он работает успешно, вы сможете увидеть URI изображения в конце вывода.
# Build Docker Container %%sh cd container chmod +x model/train chmod +x model/serve sm-docker build . --repository sagemaker-iris-rule:latest --no-logs
В демонстрационных целях мы запустим задание обучения дерева решений перед развертыванием бизнес-правила. Этот шаг можно отложить на потом, когда вы будете готовы создать более сложную модель машинного обучения после развертывания бизнес-правил. Обратите внимание, что выполнение этого шага может занять несколько минут.
# Train Model ## Note that this model is trained for demo purposes only - it's not the model that we deploy prefix = 'sagemaker-iris-rule' role = get_execution_role() WORK_DIRECTORY = 'data' data_location = sess.upload_data(WORK_DIRECTORY, key_prefix=prefix) sess = sage.Session() account = sess.boto_session.client('sts').get_caller_identity()['Account'] region = sess.boto_session.region_name image = '{}.dkr.ecr.{}.amazonaws.com/sagemaker-iris-rule:latest'.format(account, region) model = sage.estimator.Estimator(image, role, instance_count=1, instance_type='ml.c4.2xlarge', output_path='s3://{}/output'.format(sess.default_bucket()), sagemaker_session=sess) file_location = data_location + '/iris.csv' model.fit(file_location)
Развернуть бизнес-правило на данном этапе очень просто: просто вызовите метод deploy
из нашего экземпляра model
и укажите тип экземпляра, который вы хотите использовать для размещения. Опять же, это может занять несколько минут.
# Deploy Rule predictor = model.deploy(initial_instance_count=1, instance_type='ml.m4.xlarge', serializer=CSVSerializer())
Теперь вы можете протестировать развертывание правила, сгенерировав некоторые образцы данных и выполнив вывод по ним, используя конечную точку размещенной модели:
# Run Inference on Test Data tdf = pd.read_csv(file_location, header=None) tdf.drop(tdf.columns[[0]], axis=1, inplace=True) tdf = tdf.sample(10) print(predictor.predict(tdf.values).decode('utf-8'))
Наконец, если вы хотите удалить конечную точку модели, просто выполните:
# Cleanup sess.delete_endpoint(predictor.endpoint_name)
Следующие шаги
По мере того, как области науки о данных продолжают расти и развиваться, все больше ожидается, что ученые, работающие с данными, смогут независимо внедрять свои идеи в производство. Хостинг SageMaker — отличный вариант как для размещения бизнес-правил, так и для модели машинного обучения, если вы работаете в среде AWS. Если вы хотите увидеть больше практических советов по науке о данных, нажмите «Подписаться» рядом с моим именем и следите за обновлениями! А сейчас до свидания :)