Често има нужда да се абстрахират детайлите на вашия модел на машинно обучение и просто да се внедри или интегрира с лесни за използване крайни точки на API. Например, ние можем да предоставим крайна точка на URL, чрез която всеки може да направи POST заявка и ще получи JSON отговор за това, което моделът е заключил, без да се притеснява за неговите технически характеристики.

В този урок ще създадем сървър за обслужване на TensorFlow, за да внедрим нашата InceptionV3 конволюционна невронна мрежа за класификация на изображения (CNN), изградена в Keras. След това ще създадем прост Flask сървър, който ще приеме POST заявка и ще извърши предварителна обработка на изображения, необходима за сървъра за обслужване на Tensorflow, и ще върне JSON отговор.

Какво е обслужване на TensorFlow?

Сервирането е начинът, по който прилагате модела на машинно обучение, след като сте го обучили.

TensorFlow Serving прави процеса на въвеждане на модел в производство по-лесен и бърз. Тя ви позволява безопасно да внедрявате нови модели и да провеждате експерименти, като същевременно запазвате същата сървърна архитектура и API. Извън кутията той осигурява интеграция с TensorFlow, но може да бъде разширен, за да обслужва други видове модели.

Инсталиране на обслужване на TensorFlow

Предпоставка: Моля, създайте виртуална среда на Python и инсталирайте Keras с бекенда на TensorFlow в нея. Прочетете повече тук.

Забележка: Всички команди са изпълнени във виртуална среда на Python на Ubuntu 18.04.1 LTS.

Сега в същата виртуална среда изпълнете следните команди (използвайте sudo за root права):

$ apt install curl
$ echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | sudo tee /etc/apt/sources.list.d/tensorflow-serving.list && curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | sudo apt-key add -
$ apt-get update
$ apt-get install tensorflow-model-server
$ tensorflow_model_server --version
TensorFlow ModelServer: 1.10.0-dev
TensorFlow Library: 1.11.0
$ python  --version
Python 3.6.6

Можете да надстроите до по-нова версия на tensorflow-model-server с:

$ apt-get upgrade tensorflow-model-server

Преглед на директорията на това, което ще изградим

Разбирането на структурата на директорията, преди да започнем, ще ни помогне да получим ясна представа къде се намираме на всяка стъпка.

(tensorflow) ubuntu@Himanshu:~/Desktop/Medium/keras-and-tensorflow-serving$ tree -c
└── keras-and-tensorflow-serving
    ├── README.md
    ├── my_image_classifier
    │   └── 1
    │       ├── saved_model.pb
    │       └── variables
    │           ├── variables.data-00000-of-00001
    │           └── variables.index
    ├── test_images
    │   ├── car.jpg
    │   └── car.png
    ├── flask_server
    │   ├── app.py
    │   ├── flask_sample_request.py
    └── scripts
        ├── download_inceptionv3_model.py
        ├── inception.h5
        ├── auto_cmd.py
        ├── export_saved_model.py
        ├── imagenet_class_index.json
        └── serving_sample_request.py
6 directories, 15 files

Можете да получите всички тези файлове от моето хранилище на GitHub:



Експортиране на модел на Keras за обслужване на Tensorflow

За този урок ще изтеглим и запазим InceptionV3 CNN, като Imagenet тегла, в Keras, използвайки download_inceptionv3_model.py. Можете да изтеглите всеки друг модел, наличен в библиотеката keras.applications (тук) или ако сте създали свой собствен модел в Keras, можете да пропуснете тази стъпка.

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

$ python download_inceptionv3_model.py
Using TensorFlow backend.
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.5/inception_v3_weights_tf_dim_ordering_tf_kernels.h5
96116736/96112376 [==============================] - 161s 2us/step

Сега имаме нашия InceptionV3 CNN (inception.h5) запазен във формат Keras. Искаме да експортираме нашия модел във формат, който сървърът TensorFlow може да обработва. Ние правим това чрез изпълнение на export_saved_model.py скрипт.

TensorFlow предоставя формата SavedModel като универсален формат за експортиране на модели. Под капака, нашият модел Keras е напълно специфициран по отношение на обекти на TensorFlow, така че можем да го експортираме добре с помощта на методите на Tensorflow. TensorFlow предоставя функция за удобство tf.saved_model.simple_save(), която абстрахира някои от тези подробности и работи добре за повечето случаи на употреба.

Изход:

$ python export_saved_model.py
WARNING:tensorflow:No training configuration found in save file: the model was *not* compiled. Compile it manually.

Получаваме това предупреждение, защото сме изтеглили предварително обучен модел. Можем да използваме този модел за извод такъв, какъвто е, но ако искаме да го обучим допълнително, трябва да изпълним функцията compile(), след като я заредим. Това предупреждение може спокойно да бъде игнорирано засега. След изпълнение на този скрипт, следните файлове се записват в директория my_image_classifier:

├── my_image_classifier
   └── 1
       ├── saved_model.pb
       └── variables
           ├── variables.data-00000-of-00001
           └── variables.index
2 directories, 3 files

Да предположим, че искаме да актуализираме нашия модел в бъдеще (може би защото сме събрали повече данни за обучение и сме обучили модела на актуализирания набор от данни), можем да го направим чрез,

  1. Стартиране на същия скрипт на новия модел keras
  2. Актуализиране на export_path = ‘../my_image_classifier/1’ до export_path = ‘../my_image_classifier/2’ в export_saved_model.py

TensorFlow Serving автоматично ще открие новата версия на модела в директория my_image_classifier и ще я актуализира в сървъра.

Стартиране на сървъра за обслужване на TensorFlow

За да стартирате TensorFlow Serving сървър на вашата локална машина, изпълнете следната команда:

$ tensorflow_model_server --model_base_path=/home/ubuntu/Desktop/Medium/keras-and-tensorflow-serving/my_image_classifier --rest_api_port=9000 --model_name=ImageClassifier
  • --model_base_path: Това трябва да е абсолютен път, в противен случай ще получите грешка, казваща:
Failed to start server. Error: Invalid argument: Expected model ImageClassifier to have an absolute path or URI; got base_path()=./my_image_classifier
  • --rest_api_port: Tensorflow Serving ще стартира gRPC ModelServer на порт 8500 и REST API ще бъде достъпен на порт 9000.
  • --model_name: Това ще бъде името на вашия обслужващ сървър, чрез който ще изпратите POST заявка. Можете да въведете произволно име тук.

Тестваме нашия сървър за обслужване на TensorFlow

Скриптът serving_sample_request.py прави POST заявка към сървъра за обслужване на TensorFlow. Входното изображение се предава чрез аргумент на командния ред.

Изход:

$ python serving_sample_request.py -i ../test_images/car.png
Using TensorFlow backend.
[["n04285008", "sports_car", 0.998414], ["n04037443", "racer", 0.00140099], ["n03459775", "grille", 0.000160794], ["n02974003", "car_wheel", 9.57862e-06], ["n03100240", "convertible", 6.01581e-06]]

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

Защо се нуждаем от Flask сървър?

Както виждаме, изпълнихме някои стъпки за предварителна обработка на изображението в serving_sample_request.py (извикващ клиент). Следват причините да създадете Flask сървър върху сървъра за обслужване на TensorFlow:

  • Когато предоставяме нашата крайна точка на API на екипа за интерфейс, трябва да сме сигурни, че няма да ги затрупаме с технически подробности за предварителна обработка.
  • Може да не винаги разполагаме с бекенд сървър на Python (напр. Node.js сървър), така че използването на библиотеки numpy и keras за предварителна обработка може да е трудно.
  • Ако планираме да обслужваме множество модели, тогава ще трябва да създадем множество сървъри за обслужване на TensorFlow и ще трябва да добавим нови URL адреси към нашия фронтенд код. Но нашият Flask сървър ще запази URL адреса на домейна същия и трябва само да добавим нов маршрут (функция).
  • Осигуряването на достъп въз основа на абонамент, обработка на изключения и други задачи могат да се извършват в приложението Flask.

Това, което се опитваме да направим, е да премахнем тясното свързване между сървърите за обслужване на TensorFlow и нашия интерфейс.

За този урок ще създадем Flask сървър на същата машина и в същата виртуална среда като тази на TensorFlow Serving и ще използваме инсталираните библиотеки. В идеалния случай и двете трябва да работят на отделни машини, тъй като по-голям брой заявки биха довели до забавяне на Flask сървъра поради извършваната предварителна обработка на изображения. Освен това един сървър на Flask може да не е достатъчен, ако броят на заявките е наистина голям. Може също така да се нуждаем от система за опашка, ако имаме множество потребители на предния интерфейс. Въпреки това можем да използваме този метод, за да разработим задоволително доказателство за концепцията.

Създаване на Flask сървър

Предпоставка: Инсталирайте Flask във виртуална среда на python от тук.

Трябва ни само един app.py файл, за да създадем нашия Flask сървър.

Отидете в директорията, където сте запазили вашия app.py файл и стартирайте Flask сървъра със следната команда:

$ export FLASK_ENV=development && flask run --host=0.0.0.0
  • FLASK_ENV=development: Това активира режима за отстраняване на грешки, който основно ви дава пълни регистрационни файлове за грешки. Не използвайте това в производствена среда.
  • Командата flask run автоматично изпълнява файла app.py в текущата директория.
  • --host=0.0.0.0: Това ви позволява да правите заявки към сървъра на Flask от всяка друга машина. За да направите заявка от друга машина, ще трябва да посочите IP адреса на машината, на която работи сървърът на Flask, вместо localhost.

Изход:

* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 1xx-xxx-xx4
Using TensorFlow backend.

Стартирайте сървъра за обслужване на TensorFlow, като използвате същата предишна команда:

$ tensorflow_model_server --model_base_path=/home/ubuntu/Desktop/Medium/keras-and-tensorflow-serving/my_image_classifier --rest_api_port=9000 --model_name=ImageClassifier

Ето скрипт (auto_cmd.py) за автоматизиране на стартирането и спирането на двата сървъра (TensorFlow Serving и Flask). Можете да модифицирате този скрипт и за повече от два сървъра.

Не забравяйте да промените пътя на ред 10 от auto_cmd.py, за да го накарате да сочи към директорията на вашия app.py. Може също да се наложи да промените ред 6, за да го накарате да сочи към контейнера на вашата виртуална среда. След това можете да изпълните горния скрипт от всяка директория, като изпълните следното във вашия терминал:

$ python auto_cmd.py

Тестваме нашия Flask сървър и TensorFlow Serving сървър

Правим примерна заявка с помощта на скрипта flask_sample_request.py. Скриптът основно имитира заявка от интерфейса:

  1. Взимаме входно изображение, кодираме го във формат base64 и го изпращаме до нашия Flask сървър с помощта на POST заявка.
  2. Сървърът на Flask декодира това base64 изображение и го обработва предварително за нашия сървър за обслужване на TensorFlow.
  3. След това Flask сървърът прави POST заявка към нашия обслужващ сървър TensorFlow и декодира отговора.
  4. Декодираният отговор се форматира и изпраща обратно към интерфейса.

Изход:

$ python flask_sample_request.py -i ../test_images/car.png
[
  [
    "n04285008", 
    "sports_car", 
    0.998414
  ], 
  [
    "n04037443", 
    "racer", 
    0.00140099
  ], 
  [
    "n03459775", 
    "grille", 
    0.000160794
  ], 
  [
    "n02974003", 
    "car_wheel", 
    9.57862e-06
  ], 
  [
    "n03100240", 
    "convertible", 
    6.01581e-06
  ]
]

Понастоящем нашият flask сървър има само един маршрут за нашия единствен сървър за обслужване на Tensorflow. Можем да обслужваме множество модели, като създаваме множество сървъри за обслужване на Tensorflow на различна или една и съща машина. За това просто трябва да добавим повече маршрути (функции) към нашия app.py файл и да извършим необходимата специфична за модела предварителна обработка в него. Можем да предоставим тези маршрути на нашия фронтенд екип, за да извика моделите според изискванията.

Обработване на HTTP заявка от различни източници

Помислете за сценарий, при който правим POST заявка с помощта на Angular, нашият Flask сървър получава заглавка OPTIONS, а не POST, защото,

  • Уеб приложение прави HTTP заявка от кръстосан произход, когато изисква ресурс, който има различен произход (домейн, протокол и порт) от неговия собствен произход.
  • CORS (Cross Origin Resource Sharing) е механизъм, който използва допълнителни HTTP заглавки, за да каже на браузъра да позволи на уеб приложение, работещо в един източник (домейн), да има разрешение за достъп до избрани ресурси от сървър от различен произход. Прочетете повече за CORS тук.

Следователно Angular не получава никакъв отговор от сървъра на Flask. За да разрешим това, трябва да активираме Flask-CORS в нашия app.py. Научете повече за това тук.

Заключение

И това е всичко, от което се нуждаем, за да обслужваме нашия модел на машинно обучение. TensorFlow Serving прави наистина лесно интегрирането на машинно обучение в уебсайтове и други приложения. С много готови модели, налични в keras („тук“), е възможно да се разработят супер полезни приложения с минимални познания за машинно обучение и алгоритми за дълбоко обучение.

Ако сте намерили този урок за полезен, моля, споделете го с приятелите си и поздравете :-). Ако имате някакви въпроси, обратна връзка или предложения, уведомете ме в коментарите. Също така можете да се свържете с мен в Twitter и LinkedIn. Има толкова много за споделяне с всички вас, а аз тепърва започвам. Очаквайте още!