- tocdepth
2
Начало работы с деплоями
В этом документе описаны условия и алгоритм работы с деплоями на платформе ML Space и приведен пример развертывания модели для распознавания кошек и собак на изображениях.
Предварительные условия
Для развертывания модели в модуле Deployments необходимо:
обучить и сериализовать модель;
создать serving-скрипт, описывающий взаимодействие с моделью;
загрузить обученную модель и serving-скрипт в объектное хранилище S3 через интерфейс или с помощью сторонних приложений.
Работа с модулем Deployments
Работа с модулем предполагает следующую последовательность действий:
Сборка 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)
Также у пользователя есть serving-скрипт, который описывает взаимодействие с моделью.
Код serving-скрипта
import kfserving import boto3 from typing import List, Dict import re import os import tensorflow as tf from tensorflow.keras.preprocessing.image import load_img from tensorflow.keras.preprocessing.image import img_to_array from tensorflow.keras.models import load_model import numpy as np import json class KFServingExplainModel(kfserving.KFModel): def __init__(self, name: str): super().__init__(name) self.name = name self.ready = False self.model = None self.gpu = True def load(self): self.model = load_model('final_model.h5') self.ready = True def predict(self, request: Dict) -> Dict: image_link = request['instances'][0]['image_link'] img = "123.jpg" session = boto3.session.Session() s3_client = session.client( service_name='s3', aws_access_key_id='<INPUT S3 ACCESS KEY HERE>', aws_secret_access_key='<INPUT S3 SECRET KEY HERE>', endpoint_url='<INPUT S3 CREDENTIALS HERE>', region_name='ru-1a' ) s3_client.download_file('<INPUT S3 BUCKETNAME CREDENTIALS HERE>', image_link, img) img = load_img(img, target_size=(224, 224)) img = img_to_array(img) img = img.reshape(1, 224, 224, 3) img = img.astype('float32') img = img - [123.68, 116.779, 103.939] result = self.model.predict(img) result = result[0][0] if(result >= 0.5): result = 'dog' elif(result < 0.5): result = 'cat' # result = json.dumps(str(result)) # print(type(result)) return {"predictions": result} if __name__ == "__main__": x = re.compile('(kfserving-\d+)').search(os.environ.get('HOSTNAME')) name = "kfserving-default" if x: name = x[0] model = KFServingExplainModel(name) model.load() kfserving.KFServer(workers=1).start([model])
Задача состоит в том, чтобы развернуть эту модель и впоследствии передавать ей новые данные в виде HTTP-запросов.
Для решения поставленной задачи необходимо:
Сериализовать модель, например, в формат h5:
model.save('final_model.h5')
Загрузить модель и serving-скрипт в бакет пользователя на S3.
Собрать Docker-образ c моделью на основе кастомного образа.
Развернуть образ в модуле. Обратите внимание на возможность динамически изменять конфигурацию деплоя.
После развертывания образа можно передавать модели новые данные в виде HTTP-запросов. Подробнее см. Отправить синхронный HTTP-запрос к развернутой модели.
для Dev & Test