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

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

А вот и OpenVino, набор инструментов с открытым исходным кодом для оптимизации и развертывания моделей глубокого обучения, разработанный Intel. Он может улучшить производительность и эффективность модели на различных аппаратных платформах. Можно также развернуть преобразованные модели OpenVino в облачные экземпляры, такие как AWS C5, которые имеют выделенные процессоры Intel и будут очень эффективны для выполнения выводов на этих оптимизированных моделях.

В этой статье я покажу вам пример преобразования модели Pytorch CycleGAN в OpenVino и выполнения вывода с тем же, а также наблюдайте, как это помогает улучшить задержку. Сначала мы преобразуем модель Pytorch в Onnx, а затем в OpenVino. Для целей этой статьи мы будем использовать предварительно обученную модель Yosemite summer-to-winter от CycleGAN, а также их конвейер логического вывода.

Конвейер преобразования Pytorch в Onnx

### Assuming you have cloned the Cycle GAN repo from github: https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix
### run download_cyclegan_model.sh script to download pretrained summer2winter_yosemite_pretrained model (instructions on github page)
### Create a jupyter notebook and follow the below code snippets

from models import create_model
from options.test_options import TestOptions
import torch
from polygraphy.backend.onnx import fold_constants
import onnx

opt = TestOptions.parse()
opt.netG = 'resnet_9blocks'
opt.norm = 'instance'
opt.checkpoints_dir = './checkpoints' ### directory storing the pre-trained model
opt.name = 'summer2winter_yosemite_pretrained'

model = create_model(opt)
model.setup(opt)

### conversion to onnx
dummy_inp = torch.rand(1, 3, 256, 256)
onnx_filepath = './summer2winter_yosemite.onnx'
torch.onnx.export(model, dummy_inp, onnx_filepath, opset_version=10, input_names = ['inp_img'])

### optional step to do Constant folding which involves pre-computing expressions that do not depend on runtime information
converted_onnx_model = onnx.load('./summer2winter_yosemite.onnx')
constant_folded_model = fold_constants(onnx_model)
onnx.save(constant_folded_model, './summer2winter_yosemite_folded.onnx')

### This will give you converted onnx model, which can itself be used for on-device deployment

Установка OpenVinoдокументы

python3 -m venv openvino_env

source openvino_env/bin/activate

python -m pip install --upgrade pip

pip install openvino-dev==2022.1.0. ### tested on this version currently

Тестовая установка OpenVino

mo -h ### This will return the help message for Model Optimizer if installation finished successfully

Преобразование Onnx в OpenVino

### To convert, run the following in your terminal (you can use either onnx model or the folded onnx model)
### input_model - specify your input onnx file
### data_type - use fp16 to convert model to fp16 precision for better performance
### output_dir - directory where your openvino files will be saved

mo --input_model summer2winter_yosemite_folded.onnx --data_type fp16 --output_dir "./summer2winter_yosemite_openvino"

После выполнения он создаст следующие 3 файла в вашем каталоге.

summer2winter_yosemite_folded.bin - this contains the model weights ~23 Mb
summer2winter_yosemite_folded.mapping - ~15 Kb
summer2winter_yosemite_folded.xml - this contrains the model structure ~175 Kb

Теперь, когда у нас есть модели Pytorch и OpenVino, давайте сделаем вывод на приведенном ниже примере изображения и сравним их время выполнения и качественные результаты.

### Pytorch Model Inference

from util.util import tensor2im
from data.base_dataset import get_transform
from PIL import Image
import numpy as np

input_image_filename = 'Yosemite_summer.jpg'
input_image = Image.open(input_image_filename).convert('RGB')
transformation = get_transform(opt, grayscale = False)
transformed_img = transformation(input_image).unsqueeze(0)

if opt.eval:
  model.eval()
with torch.no_grad():
  output_image = model.netG_A(transformed_img)

output_image = tensor2im(output_image) ### final Pytorch result image

### OpenVino Model Inference
from openvino.inference_engine import IECore, IENetwork
from openvino.runtime import Core

ie_obj = IECore()

openvino_network = ie_obj.read_network(model = 'summer2winter_yosemite_folded.xml', weights = 'summer2winter_yosemite_folded.bin')
executable_network = ie_obj.load_network(network = openvino_network, device='CPU')

openvino_output = executable_network.infer({'inp_img': transformed_img})

arr_key = list(openvino_output.keys())[0] ### get key for putput image
openvino_output_img = torch.from_numpy(np.asarray(openvino_output[arr_key])) 
openvino_output_image = tensor2im(openvino_output_img) ### final OpenVino result image

Построение полученных изображений для сравнения качества

import matplotlib.pyplot as plt

plt.figure(figsize = (30, 30))
plt.subplot(1, 2, 1)
plt.gca().set_title('Pytorch Output', fontsize = 'xx-large')
plt.imshow(output_image)

plt.subplot(1, 2, 2)
plt.gca().set_title('OpenVino Output', fontsize = 'xx-large')
plt.imshow(openvino_output_image)

Из приведенных выше изображений мы видим, что между двумя выходными изображениями почти нет заметных различий. Кроме того, при сравнении времени выполнения логического вывода для моделей Pytorch и OpenVino для 19 запусков было замечено, что модель summer2winter_yosemite CycleGAN OpenVino работает на 50 % быстрее. по сравнению с Pytorch, что является значительным преимуществом, если мы пытаемся интегрировать эту модель в приложение для реального использования.

Заключение

OpenVino – это набор инструментов с открытым исходным кодом, представленный Intel для оптимизации моделей глубокого обучения. Он представил новый формат представления промежуточного графа, известный как IR, вместе с набором операций для представления сети глубокого обучения, которая обычно представляется в виде ориентированного графа. Он использует файл XML и двоичный файл, представляющий график или IR. Чтобы узнать больше об IR и Opsets, вы можете обратиться к их официальной документации здесь.

OpenVino определенно сделал путь к производственной реализации модели глубокого обучения намного более эффективным. Мы можем развертывать эти модели не только на различных аппаратных устройствах, но и в облачных экземплярах для бесперебойной работы приложений.

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

Если вам понравился этот урок и вы нашли его полезным, подпишитесь на другие интересные блоги и уроки!