הצג באתר TensorFlow.org | הפעל בגוגל קולאב | הצג ב-GitHub | הורד מחברת | ראה דגם TF Hub |
TensorFlow Hub הוא מאגר של דגמי TensorFlow שהוכשרו מראש.
מדריך זה מדגים כיצד:
- השתמש בדגמים מ- TensorFlow Hub עם
tf.keras
. - השתמש במודל סיווג תמונה מ- TensorFlow Hub.
- בצע לימוד העברה פשוט כדי לכוונן מודל עבור שיעורי תמונה משלך.
להכין
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
תתחיל בשימוש במודל מסווג שהוכשר מראש במערך הנתונים של ה-benchmark של 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
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 אלמנטים של לוגיטים, המדרג את ההסתברות של כל מחלקה לתמונה.
ניתן למצוא את המזהה ברמה הגבוהה ביותר עם 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())
לימוד העברה פשוט
אבל מה אם אתה רוצה ליצור מסווג מותאם אישית באמצעות מערך נתונים משלך שיש לו מחלקות שאינן כלולות במערך הנתונים המקורי של ImageNet (שהמודל שהוכשר מראש הוכשר עליו)?
כדי לעשות זאת, אתה יכול:
- בחר דגם מאומן מראש מ- TensorFlow Hub; ו
- אמן מחדש את השכבה העליונה (האחרונה) כדי לזהות את המחלקות ממערך הנתונים המותאם אישית שלך.
מערך נתונים
בדוגמה זו, תשתמש במערך הנתונים של TensorFlow flowers:
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")
התוצאות רחוקות מלהיות מושלמות, אבל הגיוניות בהתחשב בעובדה שאלו לא השיעורים אליהם הוכשרה הדוגמנית (חוץ מ"דייזי").
הורד את הדגם חסר הראש
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")
ייצא וטען מחדש את הדגם שלך
כעת לאחר שאימנת את הדגם, ייצא אותו כ-SaveModel לשימוש חוזר מאוחר יותר.
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")
הצעדים הבאים
אתה יכול להשתמש ב- SavedModel כדי לטעון להסקת מסקנות או להמיר אותו למודל TensorFlow Lite (ללמידת מכונה במכשיר) או למודל TensorFlow.js (ללמידת מכונה ב-JavaScript).
גלה מדריכים נוספים כדי ללמוד כיצד להשתמש במודלים מאומנים מראש מ- TensorFlow Hub במשימות תמונה, טקסט, אודיו ווידאו.