انتقال یادگیری با TensorFlow Hub

مشاهده در TensorFlow.org در Google Colab اجرا شود در GitHub مشاهده کنید دانلود دفترچه یادداشت مدل TF Hub را ببینید

TensorFlow Hub یک مخزن از مدل های TensorFlow از پیش آموزش دیده است.

این آموزش نشان می دهد که چگونه:

  1. از مدل های TensorFlow Hub با tf.keras استفاده کنید.
  2. از یک مدل طبقه بندی تصویر از TensorFlow Hub استفاده کنید.
  3. آموزش انتقال ساده را انجام دهید تا یک مدل را برای کلاس های تصویر خود تنظیم کنید.

برپایی

import numpy as np
import time

import PIL.Image as Image
import matplotlib.pylab as plt

import tensorflow as tf
import tensorflow_hub as hub

import datetime

%load_ext tensorboard

یک طبقه بندی کننده ImageNet

شما با استفاده از یک مدل طبقه‌بندی‌کننده که از قبل بر روی مجموعه داده‌های معیار ImageNet آموزش داده شده است، شروع می‌کنید — بدون نیاز به آموزش اولیه!

طبقه بندی کننده را دانلود کنید

یک مدل از پیش آموزش دیده MobileNetV2 را از TensorFlow Hub انتخاب کنید و آن را به عنوان یک لایه Keras با hub.KerasLayer . هر مدل طبقه‌بندی کننده تصویر سازگار از TensorFlow Hub، از جمله نمونه‌های ارائه‌شده در کشویی زیر، در اینجا کار می‌کند.

mobilenet_v2 ="https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/4"
inception_v3 = "https://tfhub.dev/google/imagenet/inception_v3/classification/5"

classifier_model = mobilenet_v2
IMAGE_SHAPE = (224, 224)

classifier = tf.keras.Sequential([
    hub.KerasLayer(classifier_model, input_shape=IMAGE_SHAPE+(3,))
])

آن را روی یک تصویر اجرا کنید

برای امتحان مدل، یک تصویر را دانلود کنید:

grace_hopper = tf.keras.utils.get_file('image.jpg','https://storage.googleapis.com/download.tensorflow.org/example_images/grace_hopper.jpg')
grace_hopper = Image.open(grace_hopper).resize(IMAGE_SHAPE)
grace_hopper
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/grace_hopper.jpg
65536/61306 [================================] - 0s 0us/step
73728/61306 [====================================] - 0s 0us/step

png

grace_hopper = np.array(grace_hopper)/255.0
grace_hopper.shape
(224, 224, 3)

یک بعد دسته ای اضافه کنید (با np.newaxis ) و تصویر را به مدل منتقل کنید:

result = classifier.predict(grace_hopper[np.newaxis, ...])
result.shape
(1, 1001)

نتیجه یک بردار 1001 عنصری از logit ها است که احتمال هر کلاس را برای تصویر رتبه بندی می کند.

شناسه کلاس برتر را می توان با tf.math.argmax پیدا کرد:

predicted_class = tf.math.argmax(result[0], axis=-1)
predicted_class
<tf.Tensor: shape=(), dtype=int64, numpy=653>

پیش بینی ها را رمزگشایی کنید

شناسه predicted_class (مانند 653 ) را بگیرید و برچسب های مجموعه داده ImageNet را برای رمزگشایی پیش بینی ها واکشی کنید:

labels_path = tf.keras.utils.get_file('ImageNetLabels.txt','https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
imagenet_labels = np.array(open(labels_path).read().splitlines())
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt
16384/10484 [==============================================] - 0s 0us/step
24576/10484 [======================================================================] - 0s 0us/step
plt.imshow(grace_hopper)
plt.axis('off')
predicted_class_name = imagenet_labels[predicted_class]
_ = plt.title("Prediction: " + predicted_class_name.title())

png

یادگیری انتقال ساده

اما اگر می‌خواهید با استفاده از مجموعه داده‌های خود یک طبقه‌بندی سفارشی ایجاد کنید که دارای کلاس‌هایی باشد که در مجموعه داده اصلی ImageNet گنجانده نشده‌اند (که مدل از پیش آموزش دیده روی آن آموزش داده شده است)؟

برای انجام این کار، می توانید:

  1. یک مدل از پیش آموزش دیده را از TensorFlow Hub انتخاب کنید. و
  2. لایه بالایی (آخرین) را مجدداً آموزش دهید تا کلاس ها را از مجموعه داده سفارشی خود شناسایی کنید.

مجموعه داده

در این مثال، از مجموعه داده گل های TensorFlow استفاده خواهید کرد:

data_root = tf.keras.utils.get_file(
  'flower_photos',
  'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
   untar=True)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
228818944/228813984 [==============================] - 7s 0us/step
228827136/228813984 [==============================] - 7s 0us/step

ابتدا، این داده ها را با استفاده از داده های تصویر خارج از دیسک با tf.keras.utils.image_dataset_from_directory در مدل بارگذاری کنید، که یک tf.data.Dataset تولید می کند:

batch_size = 32
img_height = 224
img_width = 224

train_ds = tf.keras.utils.image_dataset_from_directory(
  str(data_root),
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size
)

val_ds = tf.keras.utils.image_dataset_from_directory(
  str(data_root),
  validation_split=0.2,
  subset="validation",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size
)
Found 3670 files belonging to 5 classes.
Using 2936 files for training.
Found 3670 files belonging to 5 classes.
Using 734 files for validation.

مجموعه داده گل دارای پنج کلاس است:

class_names = np.array(train_ds.class_names)
print(class_names)
['daisy' 'dandelion' 'roses' 'sunflowers' 'tulips']

دوم، از آنجایی که قرارداد TensorFlow Hub برای مدل‌های تصویر انتظار ورودی‌های شناور در محدوده [0, 1] است، برای رسیدن به این هدف از لایه پیش‌پردازش tf.keras.layers.Rescaling استفاده کنید.

normalization_layer = tf.keras.layers.Rescaling(1./255)
train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y)) # Where x—images, y—labels.
val_ds = val_ds.map(lambda x, y: (normalization_layer(x), y)) # Where x—images, y—labels.

سوم، خط لوله ورودی را با استفاده از واکشی اولیه بافر با Dataset.prefetch به پایان برسانید، بنابراین می توانید داده ها را از دیسک بدون مشکلات مسدود کردن ورودی/خروجی به دست آورید.

اینها برخی از مهم ترین روش های tf.data هستند که باید هنگام بارگیری داده ها استفاده کنید. خوانندگان علاقه مند می توانند با راهنمای tf.data API اطلاعات بیشتری در مورد آنها و همچنین نحوه ذخیره داده ها در حافظه پنهان روی دیسک و سایر تکنیک ها کسب کنند.

AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
for image_batch, labels_batch in train_ds:
  print(image_batch.shape)
  print(labels_batch.shape)
  break
(32, 224, 224, 3)
(32,)
2022-01-26 05:06:19.465331: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.

طبقه بندی کننده را روی دسته ای از تصاویر اجرا کنید

اکنون، طبقه‌بندی کننده را روی یک دسته تصویر اجرا کنید:

result_batch = classifier.predict(train_ds)
predicted_class_names = imagenet_labels[tf.math.argmax(result_batch, axis=-1)]
predicted_class_names
array(['daisy', 'coral fungus', 'rapeseed', ..., 'daisy', 'daisy',
       'birdhouse'], dtype='<U30')

بررسی کنید که چگونه این پیش بینی ها با تصاویر مطابقت دارند:

plt.figure(figsize=(10,9))
plt.subplots_adjust(hspace=0.5)
for n in range(30):
  plt.subplot(6,5,n+1)
  plt.imshow(image_batch[n])
  plt.title(predicted_class_names[n])
  plt.axis('off')
_ = plt.suptitle("ImageNet predictions")

png

با توجه به اینکه اینها طبقاتی نیستند که مدل برای آنها آموزش داده شده است (به جز "دیزی") نتایج بسیار عالی هستند، اما معقول هستند.

دانلود مدل بی سر

TensorFlow Hub همچنین مدل ها را بدون لایه طبقه بندی بالایی توزیع می کند. از اینها می توان برای انجام آسان یادگیری انتقال استفاده کرد.

یک مدل از پیش آموزش دیده MobileNetV2 را از TensorFlow Hub انتخاب کنید. هر مدل بردار ویژگی تصویر سازگار از TensorFlow Hub در اینجا کار می کند، از جمله نمونه هایی از منوی کشویی.

mobilenet_v2 = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/4"
inception_v3 = "https://tfhub.dev/google/tf2-preview/inception_v3/feature_vector/4"

feature_extractor_model = mobilenet_v2

استخراج کننده ویژگی را با قرار دادن مدل از پیش آموزش داده شده به عنوان لایه Keras با hub.KerasLayer کنید. از آرگومان trainable=False برای ثابت کردن متغیرها استفاده کنید، به طوری که آموزش فقط لایه طبقه‌بندی‌کننده جدید را تغییر می‌دهد:

feature_extractor_layer = hub.KerasLayer(
    feature_extractor_model,
    input_shape=(224, 224, 3),
    trainable=False)

استخراج کننده ویژگی برای هر تصویر یک بردار 1280 برمی گرداند (اندازه دسته تصویر در این مثال 32 باقی می ماند):

feature_batch = feature_extractor_layer(image_batch)
print(feature_batch.shape)
(32, 1280)

یک سر طبقه بندی را ضمیمه کنید

برای تکمیل مدل، لایه استخراج ویژگی را در یک مدل tf.keras.Sequential و یک لایه کاملا متصل برای طبقه بندی اضافه کنید:

num_classes = len(class_names)

model = tf.keras.Sequential([
  feature_extractor_layer,
  tf.keras.layers.Dense(num_classes)
])

model.summary()
Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 keras_layer_1 (KerasLayer)  (None, 1280)              2257984   
                                                                 
 dense (Dense)               (None, 5)                 6405      
                                                                 
=================================================================
Total params: 2,264,389
Trainable params: 6,405
Non-trainable params: 2,257,984
_________________________________________________________________
predictions = model(image_batch)
predictions.shape
TensorShape([32, 5])

مدل را آموزش دهید

از Model.compile برای پیکربندی فرآیند آموزش استفاده کنید و یک پاسخ تماس tf.keras.callbacks.TensorBoard برای ایجاد و ذخیره گزارش‌ها اضافه کنید:

model.compile(
  optimizer=tf.keras.optimizers.Adam(),
  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
  metrics=['acc'])

log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(
    log_dir=log_dir,
    histogram_freq=1) # Enable histogram computation for every epoch.

حال از روش Model.fit برای آموزش مدل استفاده کنید.

برای کوتاه نگه داشتن این مثال، شما فقط برای 10 دوره آموزش خواهید دید. برای تجسم پیشرفت آموزش در TensorBoard بعداً، یک تماس TensorBoard را ایجاد و ذخیره کنید.

NUM_EPOCHS = 10

history = model.fit(train_ds,
                    validation_data=val_ds,
                    epochs=NUM_EPOCHS,
                    callbacks=tensorboard_callback)
Epoch 1/10
92/92 [==============================] - 7s 42ms/step - loss: 0.7904 - acc: 0.7210 - val_loss: 0.4592 - val_acc: 0.8515
Epoch 2/10
92/92 [==============================] - 3s 33ms/step - loss: 0.3850 - acc: 0.8713 - val_loss: 0.3694 - val_acc: 0.8787
Epoch 3/10
92/92 [==============================] - 3s 33ms/step - loss: 0.3027 - acc: 0.9057 - val_loss: 0.3367 - val_acc: 0.8856
Epoch 4/10
92/92 [==============================] - 3s 33ms/step - loss: 0.2524 - acc: 0.9237 - val_loss: 0.3210 - val_acc: 0.8869
Epoch 5/10
92/92 [==============================] - 3s 33ms/step - loss: 0.2164 - acc: 0.9373 - val_loss: 0.3124 - val_acc: 0.8896
Epoch 6/10
92/92 [==============================] - 3s 33ms/step - loss: 0.1888 - acc: 0.9469 - val_loss: 0.3070 - val_acc: 0.8937
Epoch 7/10
92/92 [==============================] - 3s 33ms/step - loss: 0.1668 - acc: 0.9550 - val_loss: 0.3032 - val_acc: 0.9005
Epoch 8/10
92/92 [==============================] - 3s 33ms/step - loss: 0.1487 - acc: 0.9619 - val_loss: 0.3004 - val_acc: 0.9005
Epoch 9/10
92/92 [==============================] - 3s 33ms/step - loss: 0.1335 - acc: 0.9687 - val_loss: 0.2981 - val_acc: 0.9019
Epoch 10/10
92/92 [==============================] - 3s 33ms/step - loss: 0.1206 - acc: 0.9748 - val_loss: 0.2964 - val_acc: 0.9046

TensorBoard را برای مشاهده نحوه تغییر معیارها در هر دوره و ردیابی سایر مقادیر اسکالر راه اندازی کنید:

%tensorboard --logdir logs/fit

پیش بینی ها را بررسی کنید

لیست مرتب نام کلاس ها را از پیش بینی های مدل بدست آورید:

predicted_batch = model.predict(image_batch)
predicted_id = tf.math.argmax(predicted_batch, axis=-1)
predicted_label_batch = class_names[predicted_id]
print(predicted_label_batch)
['roses' 'dandelion' 'tulips' 'sunflowers' 'dandelion' 'roses' 'dandelion'
 'roses' 'tulips' 'dandelion' 'tulips' 'tulips' 'sunflowers' 'tulips'
 'dandelion' 'roses' 'daisy' 'tulips' 'dandelion' 'dandelion' 'dandelion'
 'tulips' 'sunflowers' 'roses' 'sunflowers' 'dandelion' 'tulips' 'roses'
 'roses' 'sunflowers' 'tulips' 'sunflowers']

پیش بینی های مدل را ترسیم کنید:

plt.figure(figsize=(10,9))
plt.subplots_adjust(hspace=0.5)

for n in range(30):
  plt.subplot(6,5,n+1)
  plt.imshow(image_batch[n])
  plt.title(predicted_label_batch[n].title())
  plt.axis('off')
_ = plt.suptitle("Model predictions")

png

مدل خود را صادر و بارگذاری مجدد کنید

اکنون که مدل را آموزش داده‌اید، آن را به عنوان SavedModel صادر کنید تا بعداً دوباره از آن استفاده کنید.

t = time.time()

export_path = "/tmp/saved_models/{}".format(int(t))
model.save(export_path)

export_path
2022-01-26 05:07:03.429901: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/saved_models/1643173621/assets
INFO:tensorflow:Assets written to: /tmp/saved_models/1643173621/assets
'/tmp/saved_models/1643173621'

تأیید کنید که می‌توانید SavedModel را مجدداً بارگیری کنید و مدل می‌تواند نتایج یکسانی را ارائه دهد:

reloaded = tf.keras.models.load_model(export_path)
result_batch = model.predict(image_batch)
reloaded_result_batch = reloaded.predict(image_batch)
abs(reloaded_result_batch - result_batch).max()
0.0
reloaded_predicted_id = tf.math.argmax(reloaded_result_batch, axis=-1)
reloaded_predicted_label_batch = class_names[reloaded_predicted_id]
print(reloaded_predicted_label_batch)
['roses' 'dandelion' 'tulips' 'sunflowers' 'dandelion' 'roses' 'dandelion'
 'roses' 'tulips' 'dandelion' 'tulips' 'tulips' 'sunflowers' 'tulips'
 'dandelion' 'roses' 'daisy' 'tulips' 'dandelion' 'dandelion' 'dandelion'
 'tulips' 'sunflowers' 'roses' 'sunflowers' 'dandelion' 'tulips' 'roses'
 'roses' 'sunflowers' 'tulips' 'sunflowers']
plt.figure(figsize=(10,9))
plt.subplots_adjust(hspace=0.5)
for n in range(30):
  plt.subplot(6,5,n+1)
  plt.imshow(image_batch[n])
  plt.title(reloaded_predicted_label_batch[n].title())
  plt.axis('off')
_ = plt.suptitle("Model predictions")

png

مراحل بعدی

می‌توانید از SavedModel برای بارگیری برای استنتاج استفاده کنید یا آن را به یک مدل TensorFlow Lite (برای یادگیری ماشین روی دستگاه) یا یک مدل TensorFlow.js (برای یادگیری ماشین در جاوا اسکریپت) تبدیل کنید.

برای یادگیری نحوه استفاده از مدل های از پیش آموزش دیده از TensorFlow Hub در کارهای تصویری، متنی، صوتی و ویدیویی، آموزش های بیشتری را کشف کنید.