Wykrywanie obiektów w Google Cloud ML Engine

W tym poście dowiesz się jak wdrożyć model TensorFlow do wykrywania obiektów w Google Cloud ML Engine! Pokażę jak odpowiednio przygotować model, jak utworzyć nowy model do predykcji w ML Engine i jak wykorzystać przygotowany model.

ML Engine

W Google Cloud dostępna jest usługa ML Engine pozwalająca trenować i udostępniać modele głębokich sieci neuronowych. W tym poście skupimy się na wykorzystaniu ML Engine do udostępnienia wytrenowanego przez nas modelu. Usługa pozwala na wdrażanie modeli scikit-learn, XGBoost i oczywiście Tensorflow.

Pierwszym krokiem, jeżeli nigdy wcześniej nie korzystaliśmy z ML Engine, włączamy ML Engine Models API. Po kliknięciu „Enable API” musimy odczekać kilka chwil

Enable ML Engine Models API
Enable ML Engine Models API

Mamy już włączone API dla modeli, teraz możemy utworzyć pierwszy model.

Create first model in ML Engine
Create first model in ML Engine

Aby utworzyć model potrzebujemy podać jego nazwę, opis jest opcjonalny. Ja jako nazwę podaję ssd_mobilenet_v2_coco. Klikamy SAVE.

Create first model in ML Engine - fill model name
Create first model in ML Engine – fill model name

Po utworzeniu naszego pierwszego modelu w ML Engine pojawia nam się lista modeli z naszym dopiero utworzonym modelem.

Models list in GCP ML Engine
Models list in GCP ML Engine

Aby wykorzystać tak stworzony model potrzebujemy utworzyć jego wersję, do tego przyda nam się gotowy model, więc za chwilę wrócimy do ML Engine.

Przygotowanie modelu do wykrywania obiektów

Dla uproszczenia wykorzystamy model z Object Detection Model ZOO, będzie to SSD MobileNet V2. Model ten został nauczony na zbiorze MS COCO. Żeby dodatkowo uprościć proces, niczego nie będziemy instalować na naszych komputerach, wykorzystamy Cloud Shell.

Activate Cloud Shell
Activate Cloud Shell

Pobierzemy i rozpakujemy model SSD MobileNet V2:

wget http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz
tar zxvf ssd_mobilenet_v2_coco_2018_03_29.tar.gz

Pojawił nam  się katalog ssd_mobilenet_v2_coco_2018_03_29 a w nim nasz model w 3 postaciach:

  • frozen_inference_graph.pb – Zamrożony graf, wszystkie zmienne ustawione jako stałe. Model do predykcji
  • model.ckpt.* – model powstały jako wynik treningu, checkpoint od którego możemy kontynuować trening
  • saved_model – model który nas interesuje! Jego wagi nie są zamrożone, jest kompatybilny z ML Engine

Ale zaraz, co gdy trenuję model? Wtedy mam tylko checkpoint, tak? Tak! Całą paczkę w tym formacie możesz wygenerować za pomocą Model Exportera. Zrobimy to tutaj z uwagi na to, że modele z ZOO nie są w idealnej postaci do wdrożenia. Zobaczmy o co chodzi. Wykorzystamy narzędzie saved_model_cli.

saved_model_cli show --dir ssd_mobilenet_v2_coco_2018_03_29/saved_model --all

Rezultat powinien wyglądać mniej więcej tak:

MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['inputs'] tensor_info:
        dtype: DT_UINT8
        shape: (-1, -1, -1, 3)
        name: image_tensor:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['detection_boxes'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 100, 4)
        name: detection_boxes:0
    outputs['detection_classes'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 100)
        name: detection_classes:0
    outputs['detection_scores'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 100)
        name: detection_scores:0
    outputs['num_detections'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1)
        name: num_detections:0
  Method name is: tensorflow/serving/predict

Narzędzie saved_model_cli pokazuje nam informacje o wejściach i wyjściach naszego modelu w formacie saved_model. Z tych informacji możemy wyczytać że wejściowy format to macierz 4 wymiarowa typu UINT8 (liczby 0-255) – pierwszy wymiar to numer zdjęcia, bo może być ich wiele, drugi wymiar to wysokość zdjęcia, trzeci zaś szerokość, ostatni wymiar to liczba kanałów równa 3 – RGB. Z uwagi na to, że będziemy chcieli wykonywać predykcje poprzez zapytania json, będziemy chcieli przesyłać obrazy zakodowane w base64, a nie koniecznie macierz pikseli jako ASCII (oj ile by to miejsca zajęło!).

Wykonamy ponowny eksport modelu wymuszając wejście jako string, by móc podać zakodowany w base64 obraz. Pobierzemy repozytorium z exporterem i przygotujemy się do przekonwertowania modelu. Postępujemy zgodnie z Installation

git clone https://github.com/tensorflow/models.git
cd models/research
protoc object_detection/protos/*.proto --python_out=.
export PYTHONPATH=$PYTHONPATH:$HOME/models/research:$HOME/models/research/slim
echo "export PYTHONPATH=$PYTHONPATH:$HOME/models/research:$HOME/models/research/slim" >> ~/.bashrc

Jesteśmy prawie gotowi na uruchomienie, jeszcze tylko biblioteki. Korzystamy z TensorFlow 1.10 z uwagi na kompatybilność wyeksportowanego modelu z wersją TF w ML Engine. Obencie TF jest w wersji 1.12, a w ML Engine możemy skorzystać maksymalnie z 1.10.

pip3 install tensorflow==1.10.0 --upgrade
pip3 install --user Cython contextlib2 pillow lxml jupyter matplotlib

A więc czyżby to już? Tak i nie, my jesteśmy gotowi, ale w konfiguracji ściągniętego modelu jest błąd (Tak, jest tam błąd), więc poprawimy go najpierw usuwajc linię:

batch_norm_trainable: true

z pliku ssd_mobilenet_v2_coco_2018_03_29/pipeline.config

vi ssd_mobilenet_v2_coco_2018_03_29/pipeline.config

Teraz już możemy uruchomić export modelu:

python3 models/research/object_detection/export_inference_graph.py --input_type encoded_image_string_tensor --pipeline_config_path ssd_mobilenet_v2_coco_2018_03_29/pipeline.config --trained_checkpoint_prefix ssd_mobilenet_v2_coco_2018_03_29/model.ckpt --output_directory ssd_model_string

Dużo outputu. Dużo, ale powinien pojawić nam się katalog ssd_model_string/ z wyeksportowanym modelem. Sprawdzimy wejście naszego modelu:

saved_model_cli show --dir ssd_model_string/saved_model --all

I teraz wejście naszego modelu to string:

MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['inputs'] tensor_info:
        dtype: DT_STRING
        shape: (-1)
        name: encoded_image_string_tensor:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['detection_boxes'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 100, 4)
        name: detection_boxes:0
    outputs['detection_classes'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 100)
        name: detection_classes:0
    outputs['detection_scores'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 100)
        name: detection_scores:0
    outputs['num_detections'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1)
        name: num_detections:0
  Method name is: tensorflow/serving/predict

Upload modelu do Storage Bucketu

Nasz wyeksportowany model jest gotowy, nasz model w ML Engine również, teraz chcielibyśmy utworzyć jego pierwszą wersję, ale do tego potrzebujemy przesłać model do Storage Bucketu. Jeżeli masz już jakiś, możesz go wykorzystać, jeśli nie to utwórz nowy podając lokalizację i unikalną nazwę.

Create Storage Bucket
Create Storage Bucket

Skopiujemy nasz model do naszego Bucketu wykorzystując narzędzie gsutil

gsutil cp -r ssd_model_string gs://NAZWA_TWOJEGO_BUCKETU

Tworzenie wersji modelu w ML Engine

Mamy już wszystko co niezbędne, klikamy w nasz model w ML Engine Models i klikamy create version.

Create a version of the model - ML Engine
Create a version of the model – ML Engine

Uzupełniamy dane i klikamy save.

TensorFlow Saved Model as Version in ML Engine
TensorFlow Saved Model as Version in ML Engine

Po dłuższej chwili model powinien zacząć działać – zielona ikona. To dobry moment na przerwę, ja byłem w sklepie w międzyczasie. Tak to wygląda:

Succesfully created version of a model in ML Engine
A succesfully created version of a model in ML Engine

Predykcja z wykorzystaniem modelu

Przygotujemy zdjęcie do predykcji i zapiszamy je do pliku instance.json w formacie base64.

wget https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/test_images/image1.jpg
echo {\"inputs\":{\"b64\":\"$(base64 image1.jpg)\"}} > instance.json

A następnie wykonamy predykcję:

gcloud ml-engine predict --model ssd_mobilenet_v2_coco --version version0 --json-instances instance.json

I otrzymujemy wynik:

DETECTION_BOXES                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            DETECTION_CLASSES                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       DETECTION_SCORES                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  NUM_DETECTIONS
[[0.09466058015823364, 0.3744485080242157, 0.9318303465843201, 0.981620192527771], [0.01541098952293396, 0.012350127100944519, 0.8634837865829468, 0.32115042209625244], [0.009715914726257324, 0.2869885563850403, 0.7213219404220581, 0.6651993989944458], [0.0, 0.3330763280391693, 0.514610767364502, 0.6734130382537842], [0.04345259070396423, 0.26753389835357666, 0.8989118337631226, 0.781010627746582], [0.004425108432769775, 0.3637745976448059, 0.3391636610031128, 0.6960598826408386], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]  [18.0, 18.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]  [0.9828254580497742, 0.8657804131507874, 0.7905182838439941, 0.5871506929397583, 0.43748635053634644, 0.41519099473953247, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  6.0

Otrzymaliśmy 6 wykryć

  1. klasa 18 (dog)
    bbox: 0.0946, 0.374, 0.932, 0.982
    score: 0.983
  2. klasa 18 (dog)
    bbox: 0.015, 0.012, 0.863, 0.321
    score: 0.866
  3. klasa 1 (person)
    bbox: 0.010, 0.287, 0.721, 0.665
    score: 0.791
  4. klasa 1 (person)
    bbox: 0.0, 0.333, 0.515, 0.673
    score: 0.587
  5. klasa 1 (person)
    bbox: 0.043, 0.268, 0.899, 0.781
    score: 0.437
  6. klasa 1 (person)
    bbox: 0.004, 0.364, 0.339, 0.696
    score: 0.415

Istnieje jeszcze możliwość predykcji z pythona, ale to zostawiam na później!

https://cloud.google.com/ml-engine/docs/tensorflow/online-predict

Link

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *