התאמן והגיש דגם TensorFlow עם הגשת TensorFlow

מדריך זה רכבות מודל רשת עצבית לסווג תמונות של בגדים, כמו נעלי ספורט וחולצות , חוסך המודל מאומן, ואז מגיש אותו עם TensorFlow הגשה . הדגש הוא על TensorFlow הגשה, ולא הדוגמנות והדרכת TensorFlow, כך עבור דוגמא שלמה המתמקד הדוגמנות וההכשרה לראות את דוגמא הסיווג הבסיסי .

מדריך זה משתמש tf.keras , ה- API ברמה גבוהה למודלים לבנות ורכבת TensorFlow.

import sys

# Confirm that we're using Python 3
assert sys.version_info.major == 3, 'Oops, not running Python 3. Use Runtime > Change runtime type'
# TensorFlow and tf.keras
print("Installing dependencies for Colab environment")
!pip install -Uq grpcio==1.26.0

import tensorflow as tf
from tensorflow import keras

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
import os
import subprocess

print('TensorFlow version: {}'.format(tf.__version__))

צור את הדגם שלך

ייבא את מערך הנתונים של Fashion MNIST

מדריך זה משתמש אופנה MNIST הנתונים המכיל 70,000 תמונות בגווני אפור ב 10 קטגוריות. התמונות מציגות פריטי לבוש בודדים ברזולוציה נמוכה (28 על 28 פיקסלים), כפי שניתן לראות כאן:

ספרייט MNIST אופנה
איור 1. דגימות אופנה-MNIST (על ידי Zalando, רישיון MIT).

אופנה MNIST מיועד לשמש נפתח ב תחליף עבור קלאסי MNIST במערך-קרובות משמש "שלום, עולם" של תוכניות לימוד מכונה עבור ראייה ממוחשבת. אתה יכול לגשת ל- Fashion MNIST ישירות מ- TensorFlow, פשוט לייבא ולטעון את הנתונים.

fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

# scale the values to 0.0 to 1.0
train_images = train_images / 255.0
test_images = test_images / 255.0

# reshape for feeding into the model
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1)
test_images = test_images.reshape(test_images.shape[0], 28, 28, 1)

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

print('\ntrain_images.shape: {}, of {}'.format(train_images.shape, train_images.dtype))
print('test_images.shape: {}, of {}'.format(test_images.shape, test_images.dtype))
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step

train_images.shape: (60000, 28, 28, 1), of float64
test_images.shape: (10000, 28, 28, 1), of float64

אימון והעריך את המודל שלך

בואו נשתמש ב-CNN הפשוט ביותר האפשרי, מכיוון שאנחנו לא מתמקדים בחלק הדוגמנות.

model = keras.Sequential([
  keras.layers.Conv2D(input_shape=(28,28,1), filters=8, kernel_size=3, 
                      strides=2, activation='relu', name='Conv1'),
  keras.layers.Flatten(),
  keras.layers.Dense(10, name='Dense')
])
model.summary()

testing = False
epochs = 5

model.compile(optimizer='adam', 
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=[keras.metrics.SparseCategoricalAccuracy()])
model.fit(train_images, train_labels, epochs=epochs)

test_loss, test_acc = model.evaluate(test_images, test_labels)
print('\nTest accuracy: {}'.format(test_acc))
2021-12-04 10:29:34.128871: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'libcusolver.so.10'; dlerror: libcusolver.so.10: cannot open shared object file: No such file or directory
2021-12-04 10:29:34.129907: W tensorflow/core/common_runtime/gpu/gpu_device.cc:1757] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://www.tensorflow.org/install/gpu for how to download and setup the required libraries for your platform.
Skipping registering GPU devices...
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
Conv1 (Conv2D)               (None, 13, 13, 8)         80        
_________________________________________________________________
flatten (Flatten)            (None, 1352)              0         
_________________________________________________________________
Dense (Dense)                (None, 10)                13530     
=================================================================
Total params: 13,610
Trainable params: 13,610
Non-trainable params: 0
_________________________________________________________________
Epoch 1/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.7204 - sparse_categorical_accuracy: 0.7549
Epoch 2/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3997 - sparse_categorical_accuracy: 0.8611
Epoch 3/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3580 - sparse_categorical_accuracy: 0.8754
Epoch 4/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3399 - sparse_categorical_accuracy: 0.8780
Epoch 5/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3232 - sparse_categorical_accuracy: 0.8849
313/313 [==============================] - 0s 1ms/step - loss: 0.3586 - sparse_categorical_accuracy: 0.8738

Test accuracy: 0.8737999796867371

שמור את הדגם שלך

כדי לטעון דגם המיומן שלנו לתוך TensorFlow הגשה תחילה עלינו להציל אותו SavedModel פורמט. פעולה זו תיצור קובץ protobuf בהיררכיית ספריות מוגדרת היטב, ויכלול מספר גרסה. הצגת TensorFlow מאפשרת לנו לבחור איזה גרסה של מודל, או "servable" אנחנו רוצים להשתמש כאשר אנו עושים בקשות היקש. כל גרסה תיוצא לספריית משנה אחרת תחת הנתיב הנתון.

# Fetch the Keras session and save the model
# The signature definition is defined by the input and output tensors,
# and stored with the default serving key
import tempfile

MODEL_DIR = tempfile.gettempdir()
version = 1
export_path = os.path.join(MODEL_DIR, str(version))
print('export_path = {}\n'.format(export_path))

tf.keras.models.save_model(
    model,
    export_path,
    overwrite=True,
    include_optimizer=True,
    save_format=None,
    signatures=None,
    options=None
)

print('\nSaved model:')
!ls -l {export_path}
export_path = /tmp/1
2021-12-04 10:29:53.392905: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/1/assets

Saved model:
total 88
drwxr-xr-x 2 kbuilder kbuilder  4096 Dec  4 10:29 assets
-rw-rw-r-- 1 kbuilder kbuilder 78055 Dec  4 10:29 saved_model.pb
drwxr-xr-x 2 kbuilder kbuilder  4096 Dec  4 10:29 variables

בדוק את הדגם השמור שלך

אנו נשתמש בכלי שורת הפקודה saved_model_cli להסתכל על MetaGraphDefs (דגמי) ו SignatureDefs (שיטות אפשר לקרוא) ב SavedModel שלנו. ראה את הדיון הזה של CLI SavedModel במדריך TensorFlow.

saved_model_cli show --dir {export_path} --all
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['__saved_model_init_op']:
  The given SavedModel SignatureDef contains the following input(s):
  The given SavedModel SignatureDef contains the following output(s):
    outputs['__saved_model_init_op'] tensor_info:
        dtype: DT_INVALID
        shape: unknown_rank
        name: NoOp
  Method name is: 

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['Conv1_input'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 28, 28, 1)
        name: serving_default_Conv1_input:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['Dense'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 10)
        name: StatefulPartitionedCall:0
  Method name is: tensorflow/serving/predict

Defined Functions:
  Function Name: '__call__'
    Option #1
      Callable with:
        Argument #1
          Conv1_input: TensorSpec(shape=(None, 28, 28, 1), dtype=tf.float32, name='Conv1_input')
        Argument #2
          DType: bool
          Value: False
        Argument #3
          DType: NoneType
          Value: None
    Option #2
      Callable with:
        Argument #1
          inputs: TensorSpec(shape=(None, 28, 28, 1), dtype=tf.float32, name='inputs')
        Argument #2
          DType: bool
          Value: False
        Argument #3
          DType: NoneType
          Value: None
    Option #3
      Callable with:
        Argument #1
          inputs: TensorSpec(shape=(None, 28, 28, 1), dtype=tf.float32, name='inputs')
        Argument #2
          DType: bool
          Value: True
        Argument #3
          DType: NoneType
          Value: None
    Option #4
      Callable with:
        Argument #1
          Conv1_input: TensorSpec(shape=(None, 28, 28, 1), dtype=tf.float32, name='Conv1_input')
        Argument #2
          DType: bool
          Value: True
        Argument #3
          DType: NoneType
          Value: None

  Function Name: '_default_save_signature'
    Option #1
      Callable with:
        Argument #1
          Conv1_input: TensorSpec(shape=(None, 28, 28, 1), dtype=tf.float32, name='Conv1_input')

  Function Name: 'call_and_return_all_conditional_losses'
    Option #1
      Callable with:
        Argument #1
          inputs: TensorSpec(shape=(None, 28, 28, 1), dtype=tf.float32, name='inputs')
        Argument #2
          DType: bool
          Value: False
        Argument #3
          DType: NoneType
          Value: None
    Option #2
      Callable with:
        Argument #1
          Conv1_input: TensorSpec(shape=(None, 28, 28, 1), dtype=tf.float32, name='Conv1_input')
        Argument #2
          DType: bool
          Value: True
        Argument #3
          DType: NoneType
          Value: None
    Option #3
      Callable with:
        Argument #1
          Conv1_input: TensorSpec(shape=(None, 28, 28, 1), dtype=tf.float32, name='Conv1_input')
        Argument #2
          DType: bool
          Value: False
        Argument #3
          DType: NoneType
          Value: None
    Option #4
      Callable with:
        Argument #1
          inputs: TensorSpec(shape=(None, 28, 28, 1), dtype=tf.float32, name='inputs')
        Argument #2
          DType: bool
          Value: True
        Argument #3
          DType: NoneType
          Value: None

זה אומר לנו הרבה על הדגם שלנו! במקרה הזה פשוט אימנו את המודל שלנו, אז אנחנו כבר יודעים את התשומות והיציאות, אבל אם לא היינו, זה יהיה מידע חשוב. זה לא אומר לנו הכל, כמו העובדה שמדובר בנתוני תמונה בגווני אפור למשל, אבל זו התחלה מצוינת.

הגישו את הדגם שלכם עם TensorFlow Serving

הוסף את URI הפצה של TensorFlow Serving כמקור חבילה:

אנחנו מתכוננים להתקין TensorFlow הגשה באמצעות המיומנות מאז Colab זה פועל בסביבה דביאן. נוסיף את tensorflow-model-server החבילה לרשימת החבילות כי המיומנות יודעת על. שימו לב שאנחנו פועלים כשורש.

import sys
# We need sudo prefix if not on a Google Colab.
if 'google.colab' not in sys.modules:
  SUDO_IF_NEEDED = 'sudo'
else:
  SUDO_IF_NEEDED = ''
# This is the same as you would do from your command line, but without the [arch=amd64], and no sudo
# You would instead do:
# 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 -

!echo "deb http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | {SUDO_IF_NEEDED} tee /etc/apt/sources.list.d/tensorflow-serving.list && \
curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | {SUDO_IF_NEEDED} apt-key add -
!{SUDO_IF_NEEDED} apt update
deb http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2943  100  2943    0     0  15571      0 --:--:-- --:--:-- --:--:-- 15571
OK
Hit:1 http://asia-east1.gce.archive.ubuntu.com/ubuntu bionic InRelease
Hit:2 http://asia-east1.gce.archive.ubuntu.com/ubuntu bionic-updates InRelease
Hit:3 http://asia-east1.gce.archive.ubuntu.com/ubuntu bionic-backports InRelease
Hit:4 https://nvidia.github.io/libnvidia-container/stable/ubuntu18.04/amd64  InRelease
Get:5 https://nvidia.github.io/nvidia-container-runtime/ubuntu18.04/amd64  InRelease [1481 B]
Get:6 https://nvidia.github.io/nvidia-docker/ubuntu18.04/amd64  InRelease [1474 B]
Ign:7 http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64  InRelease
Get:8 http://storage.googleapis.com/tensorflow-serving-apt stable InRelease [3012 B]
Hit:9 http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64  Release
Get:10 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Get:11 https://packages.cloud.google.com/apt eip-cloud-bionic InRelease [5419 B]
Get:12 http://packages.cloud.google.com/apt google-cloud-logging-wheezy InRelease [5483 B]
Hit:13 http://archive.canonical.com/ubuntu bionic InRelease
Err:11 https://packages.cloud.google.com/apt eip-cloud-bionic InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY FEEA9169307EA071 NO_PUBKEY 8B57C5C2836F4BEB
Get:15 http://storage.googleapis.com/tensorflow-serving-apt stable/tensorflow-model-server amd64 Packages [339 B]
Err:12 http://packages.cloud.google.com/apt google-cloud-logging-wheezy InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY FEEA9169307EA071 NO_PUBKEY 8B57C5C2836F4BEB
Get:16 http://storage.googleapis.com/tensorflow-serving-apt stable/tensorflow-model-server-universal amd64 Packages [348 B]
Fetched 106 kB in 1s (103 kB/s)



119 packages can be upgraded. Run 'apt list --upgradable' to see them.
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: https://packages.cloud.google.com/apt eip-cloud-bionic InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY FEEA9169307EA071 NO_PUBKEY 8B57C5C2836F4BEB
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://packages.cloud.google.com/apt google-cloud-logging-wheezy InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY FEEA9169307EA071 NO_PUBKEY 8B57C5C2836F4BEB
W: Failed to fetch https://packages.cloud.google.com/apt/dists/eip-cloud-bionic/InRelease  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY FEEA9169307EA071 NO_PUBKEY 8B57C5C2836F4BEB
W: Failed to fetch http://packages.cloud.google.com/apt/dists/google-cloud-logging-wheezy/InRelease  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY FEEA9169307EA071 NO_PUBKEY 8B57C5C2836F4BEB
W: Some index files failed to download. They have been ignored, or old ones used instead.

התקן את TensorFlow Serving

זה כל מה שאתה צריך - שורת פקודה אחת!

{SUDO_IF_NEEDED} apt-get install tensorflow-model-server
The following packages were automatically installed and are no longer required:
  linux-gcp-5.4-headers-5.4.0-1040 linux-gcp-5.4-headers-5.4.0-1043
  linux-gcp-5.4-headers-5.4.0-1044 linux-gcp-5.4-headers-5.4.0-1049
Use 'sudo apt autoremove' to remove them.
The following NEW packages will be installed:
  tensorflow-model-server
0 upgraded, 1 newly installed, 0 to remove and 119 not upgraded.
Need to get 335 MB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 http://storage.googleapis.com/tensorflow-serving-apt stable/tensorflow-model-server amd64 tensorflow-model-server all 2.7.0 [335 MB]
Fetched 335 MB in 7s (45.2 MB/s)
Selecting previously unselected package tensorflow-model-server.
(Reading database ... 264341 files and directories currently installed.)
Preparing to unpack .../tensorflow-model-server_2.7.0_all.deb ...
Unpacking tensorflow-model-server (2.7.0) ...
Setting up tensorflow-model-server (2.7.0) ...

התחל להפעיל את TensorFlow Serving

זה המקום שבו אנחנו מתחילים להפעיל את TensorFlow Serving ולטעון את המודל שלנו. לאחר טעינתו נוכל להתחיל לבצע בקשות להסיק באמצעות REST. יש כמה פרמטרים חשובים:

  • rest_api_port : הנמל, שבו תשתמש עבור בקשות REST.
  • model_name : עליך להשתמש באפשרות זו בכתובת ה- URL של בקשות REST. זה יכול להיות כל דבר.
  • model_base_path : זהו הנתיב אל הספרייה שבה שמרת המודל שלך.
os.environ["MODEL_DIR"] = MODEL_DIR
nohup tensorflow_model_server \
  --rest_api_port=8501 \
  --model_name=fashion_model \
  --model_base_path="${MODEL_DIR}" >server.log 2>&1
tail server.log

הגש בקשה לדגם שלך ב- TensorFlow Serving

ראשית, בואו נסתכל על דוגמה אקראית מנתוני הבדיקה שלנו.

def show(idx, title):
  plt.figure()
  plt.imshow(test_images[idx].reshape(28,28))
  plt.axis('off')
  plt.title('\n\n{}'.format(title), fontdict={'size': 16})

import random
rando = random.randint(0,len(test_images)-1)
show(rando, 'An Example Image: {}'.format(class_names[test_labels[rando]]))

png

אוקיי, זה נראה מעניין. כמה קשה לך לזהות את זה? כעת בואו ניצור את אובייקט ה-JSON עבור אצווה של שלוש בקשות להסיק, ונראה עד כמה המודל שלנו מזהה דברים:

import json
data = json.dumps({"signature_name": "serving_default", "instances": test_images[0:3].tolist()})
print('Data: {} ... {}'.format(data[:50], data[len(data)-52:]))
Data: {"signature_name": "serving_default", "instances": ...  [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0]]]]}

בצע בקשות REST

הגרסה החדשה ביותר של ההגשה

אנו נשלח בקשת חיזוי כ-POST לנקודת הקצה REST של השרת שלנו, ונעביר לה שלוש דוגמאות. נבקש מהשרת שלנו לתת לנו את הגרסה העדכנית ביותר של השרת שלנו על ידי אי ציון גרסה מסוימת.

# docs_infra: no_execute
!pip install -q requests

import requests
headers = {"content-type": "application/json"}
json_response = requests.post('http://localhost:8501/v1/models/fashion_model:predict', data=data, headers=headers)
predictions = json.loads(json_response.text)['predictions']

show(0, 'The model thought this was a {} (class {}), and it was actually a {} (class {})'.format(
  class_names[np.argmax(predictions[0])], np.argmax(predictions[0]), class_names[test_labels[0]], test_labels[0]))

גרסה מסוימת של ההגשה

כעת בוא נציין גרסה מסוימת של קובץ ההגשה שלנו. מכיוון שיש לנו רק אחת, בוא נבחר גרסה 1. נסתכל גם על כל שלוש התוצאות.

# docs_infra: no_execute
headers = {"content-type": "application/json"}
json_response = requests.post('http://localhost:8501/v1/models/fashion_model/versions/1:predict', data=data, headers=headers)
predictions = json.loads(json_response.text)['predictions']

for i in range(0,3):
  show(i, 'The model thought this was a {} (class {}), and it was actually a {} (class {})'.format(
    class_names[np.argmax(predictions[i])], np.argmax(predictions[i]), class_names[test_labels[i]], test_labels[i]))