Быстрый старт по работе с Deployments

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

До начала работы с сервисом необходимо подготовить обученную модель и служебный скрипт (serving script), описывающий порядок взаимодействия с моделью. См. Скрипты для прогнозирования на основе обученных моделей.

Важно

В рамках сервиса Deployments используются сериализованные модели. Для этой цели можно использовать встроенные средства фреймворка обучения, сохраняя контрольные точки в формате bin, h5, pth и др. Также модели можно сериализовать в формат h5 средствами библиотеки h5py или в формат pickle средствами библиотеки pickle.

Модели AutoML сериализовать не нужно, этот шаг выполняется по завершении обучения.

Работа с сервисом предполагает следующую последовательность действий:

  • Загрузка модели и скрипта, описывающего взаимодействие с моделью, на S3.

  • Сборка Docker-образа с моделью на основе базового или кастомного образа. В кастомном образе предполагается использование зависимостей, которые отсутствуют в базовом образе.

  • Разворачивание образа с моделью на указанной конфигурации.

  • Отправка HTTP-запросов к модели вручную или от автоматизированных систем.

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

Код обучения модели

from matplotlib import pyplot
from matplotlib.image import imread
from os import listdir
from numpy import asarray
from numpy import save
import tensorflow.keras as keras
from tensorflow.keras.preprocessing.image import load_img
from tensorflow.keras.preprocessing.image import img_to_array
from os import makedirs
from shutil import copyfile
from random import seed
from random import random

# plot dog photos from the dogs vs cats dataset
# define location of dataset
folder = 'train/'
# plot first few images
for i in range(9):
    # define subplot
    pyplot.subplot(330 + 1 + i)
    # define filename
    filename = folder + 'dog.' + str(i) + '.jpg'
    # load image pixels
    image = imread(filename)
    # plot raw pixel data
    pyplot.imshow(image)
# show the figure
pyplot.show()

# plot cat photos from the dogs vs cats dataset
# define location of dataset
folder = 'train/'
# plot first few images
for i in range(9):
    # define subplot
    pyplot.subplot(330 + 1 + i)
    # define filename
    filename = folder + 'cat.' + str(i) + '.jpg'
    # load image pixels
    image = imread(filename)
    # plot raw pixel data
    pyplot.imshow(image)
# show the figure
pyplot.show()

# load dogs vs cats dataset, reshape and save to a new file
# define location of dataset
folder = 'train/'
photos, labels = list(), list()
# enumerate files in the directory
for file in listdir(folder):
# determine class
    output = 0.0
    if file.startswith('cat'):
        output = 1.0
    # load image
    photo = load_img(folder + file, target_size=(200, 200))
    # convert to numpy array
    photo = img_to_array(photo)
    # store
    photos.append(photo)
    labels.append(output)
# convert to a numpy arrays
photos = asarray(photos)
labels = asarray(labels)
print(photos.shape, labels.shape)
# save the reshaped photos
save('dogs_vs_cats_photos.npy', photos)
save('dogs_vs_cats_labels.npy', labels)

# organize dataset into a useful structure
# create directories
dataset_home = 'dataset_dogs_vs_cats/'
subdirs = ['train/', 'test/']
for subdir in subdirs:
    # create label subdirectories
    labeldirs = ['dogs/', 'cats/']
    for labldir in labeldirs:
        newdir = dataset_home + subdir + labldir
        makedirs(newdir, exist_ok=True)
# seed random number generator
seed(1)
# define ratio of pictures to use for validation
val_ratio = 0.25
# copy training dataset images into subdirectories
src_directory = 'train/'
for file in listdir(src_directory):
    src = src_directory + '/' + file
    dst_dir = 'train/'
    if random() < val_ratio:
        dst_dir = 'test/'
    if file.startswith('cat'):
        dst = dataset_home + dst_dir + 'cats/' + file
        copyfile(src, dst)
    elif file.startswith('dog'):
        dst = dataset_home + dst_dir + 'dogs/' + file
        copyfile(src, dst)

# organize dataset into a useful structure
from os import makedirs
from os import listdir
from shutil import copyfile
# create directories
dataset_home = 'finalize_dogs_vs_cats/'
# create label subdirectories
labeldirs = ['dogs/', 'cats/']
for labldir in labeldirs:
    newdir = dataset_home + labldir
    makedirs(newdir, exist_ok=True)

# copy training dataset images into subdirectories
src_directory = 'dataset_dogs_vs_cats/train'
for file2 in listdir(src_directory):
    ext_path = src_directory + '/' + file2
    for file in listdir(ext_path):
        src = ext_path + '/' + file
        if file.startswith('cat'):
            dst = dataset_home + 'cats/' + file
            # print(dst)
            copyfile(src, dst)
        elif file.startswith('dog'):
            dst = dataset_home + 'dogs/' + file
            # print(dst)
            copyfile(src, dst)

# save the final model to file
import tensorflow.keras as keras
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Flatten
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# define cnn model
def define_model():
    # load model
    model = VGG16(include_top=False, input_shape=(224, 224, 3))
    # mark loaded layers as not trainable
    for layer in model.layers:
        layer.trainable = False
        # add new classifier layers
        flat1 = Flatten()(model.layers[-1].output)
        class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)
        output = Dense(1, activation='sigmoid')(class1)
        # define new model
        model = Model(inputs=model.inputs, outputs=output)
        # compile model
        opt = SGD(lr=0.001, momentum=0.9)
        model.compile(optimizer=opt, loss='binary_crossentropy', metrics=['accuracy'])
    return model

# run the test harness for evaluating a model
def run_test_harness():
# define model
    model = define_model()
    # create data generator
    datagen = ImageDataGenerator(featurewise_center=True)
    # specify imagenet mean values for centering
    datagen.mean = [123.68, 116.779, 103.939]
    # prepare iterator
    train_it = datagen.flow_from_directory('finalize_dogs_vs_cats/',
        class_mode='binary', batch_size=64, target_size=(224, 224))
    # fit model
    # model = keras.utils.multi_gpu_model(model, gpus=8)
    model.fit_generator(train_it, steps_per_epoch=len(train_it), epochs=10, verbose=1)

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

Для решения поставленной задачи необходимо:

  1. Сериализовать модель, например, в формат h5:

    model.save('final_model.h5')
    
  2. Загрузить модель и serving-скрипт в бакет пользователя на S3 (см. Загрузка файлов).

  3. Собрать Docker-образ c моделью на основе кастомного образа.

    Для этого:

    • Перейти на вкладку Деплои.

    • Нажать кнопку Создать деплой. Откроется диалог Создать деплой.

    • Выбрать Создайте новый.

    • В поле Base image указать базовый образ.

    • Заполнить остальные поля. См. Сборка образов.

    • Нажать кнопку Создать образ и дождаться сборки образа.

  4. Развернуть образ на сервисе. См. Развертывание модели. Обратите внимание на возможность динамически изменять конфигурацию деплоя. См. Развертывание модели.

После развертывания образа можно передавать модели новые данные в виде HTTP-запросов. Подробнее см. в Отправка HTTP-запросов к сервису.