Zobacz na TensorFlow.org | Uruchom w Google Colab | Zobacz na GitHub | Pobierz notatnik | Zobacz model piasty TF |
TensorFlow Hub to repozytorium wstępnie przeszkolonych modeli TensorFlow.
Ten samouczek pokazuje, jak:
- Użyj modeli z TensorFlow Hub z
tf.keras
. - Użyj modelu klasyfikacji obrazów z TensorFlow Hub.
- Wykonaj proste uczenie transferu, aby dostroić model do własnych klas obrazów.
Ustawiać
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
Klasyfikator ImageNet
Zaczniesz od użycia modelu klasyfikatora wstępnie wytrenowanego w zestawie danych porównawczych ImageNet — nie jest wymagane wstępne szkolenie!
Pobierz klasyfikator
Wybierz wstępnie wytrenowany model MobileNetV2 z TensorFlow Hub i zapakuj go jako warstwę Keras za pomocą hub.KerasLayer
. Tutaj będzie działał dowolny zgodny model klasyfikatora obrazu z TensorFlow Hub, w tym przykłady podane w rozwijanym menu poniżej.
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,))
])
Uruchom go na jednym obrazie
Pobierz pojedynczy obraz, aby wypróbować model:
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)
Dodaj wymiar wsadowy (za pomocą np.newaxis
) i przekaż obraz do modelu:
result = classifier.predict(grace_hopper[np.newaxis, ...])
result.shape
(1, 1001)
Wynikiem jest 1001-elementowy wektor logitów, oceniający prawdopodobieństwo każdej klasy dla obrazu.
Identyfikator najwyższej klasy można znaleźć w tf.math.argmax
:
predicted_class = tf.math.argmax(result[0], axis=-1)
predicted_class
<tf.Tensor: shape=(), dtype=int64, numpy=653>
Odszyfruj przepowiednie
Weź identyfikator predicted_class
(np. 653
) i pobierz etykiety zestawu danych ImageNet, aby odszyfrować przewidywania:
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())
Prosta nauka transferu
Ale co, jeśli chcesz utworzyć niestandardowy klasyfikator przy użyciu własnego zestawu danych, który zawiera klasy, które nie są zawarte w oryginalnym zestawie danych ImageNet (na którym został przeszkolony wstępnie wytrenowany model)?
Aby to zrobić, możesz:
- Wybierz wstępnie wytrenowany model z TensorFlow Hub; oraz
- Ponownie naucz górną (ostatnią) warstwę, aby rozpoznawać klasy z niestandardowego zestawu danych.
Zbiór danych
W tym przykładzie użyjesz zestawu danych kwiatów 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
Najpierw załaduj te dane do modelu za pomocą danych obrazu z dysku za pomocą tf.keras.utils.image_dataset_from_directory
, co wygeneruje 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.
Zbiór danych o kwiatach ma pięć klas:
class_names = np.array(train_ds.class_names)
print(class_names)
['daisy' 'dandelion' 'roses' 'sunflowers' 'tulips']
Po drugie, ponieważ konwencja TensorFlow Hub dla modeli obrazu polega na oczekiwaniu zmiennoprzecinkowych danych wejściowych w zakresie [0, 1]
, użyj warstwy przetwarzania wstępnego tf.keras.layers.Rescaling
, aby to osiągnąć.
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.
Po trzecie, zakończ potok wejściowy, używając buforowanego pobierania wstępnego z Dataset.prefetch
, dzięki czemu można uzyskać dane z dysku bez problemów z blokowaniem operacji we/wy.
Oto niektóre z najważniejszych metod tf.data
, których należy używać podczas ładowania danych. Zainteresowani czytelnicy mogą dowiedzieć się więcej na ich temat, a także jak buforować dane na dysku i inne techniki, w przewodniku Lepsza wydajność z 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.
Uruchom klasyfikator na partii obrazów
Teraz uruchom klasyfikator na partii obrazów:
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')
Sprawdź, jak te przewidywania pokrywają się z obrazami:
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")
Wyniki są dalekie od doskonałych, ale rozsądne, biorąc pod uwagę, że nie są to klasy, do których trenowano model (z wyjątkiem „stokrotek”).
Pobierz model bez głowy
TensorFlow Hub dystrybuuje również modele bez najwyższej warstwy klasyfikacji. Można ich użyć do łatwego przeprowadzenia uczenia transferu.
Wybierz wstępnie wytrenowany model MobileNetV2 z TensorFlow Hub . Tutaj będzie działał dowolny zgodny model wektorowy funkcji obrazu z TensorFlow Hub, w tym przykłady z menu rozwijanego.
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
Utwórz ekstraktor elementów, owijając wstępnie wytrenowany model jako warstwę Keras za pomocą hub.KerasLayer
. Użyj argumentu trainable=False
, aby zamrozić zmienne, dzięki czemu szkolenie modyfikuje tylko nową warstwę klasyfikatora:
feature_extractor_layer = hub.KerasLayer(
feature_extractor_model,
input_shape=(224, 224, 3),
trainable=False)
Ekstraktor elementów zwraca wektor o długości 1280 dla każdego obrazu (rozmiar wsadu obrazu wynosi w tym przykładzie 32):
feature_batch = feature_extractor_layer(image_batch)
print(feature_batch.shape)
(32, 1280)
Dołącz głowicę klasyfikacyjną
Aby ukończyć model, owiń warstwę ekstraktora elementów w model tf.keras.Sequential
i dodaj w pełni połączoną warstwę do klasyfikacji:
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])
Trenuj modelkę
Użyj Model.compile
, aby skonfigurować proces uczenia i dodaj wywołanie zwrotne tf.keras.callbacks.TensorBoard
, aby utworzyć i przechowywać logi:
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.
Teraz użyj metody Model.fit
, aby wytrenować model.
Aby ten przykład był krótki, będziesz trenować tylko przez 10 epok. Aby później zwizualizować postęp szkolenia w TensorBoard, utwórz i przechowuj logi jako wywołanie zwrotne 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
Uruchom TensorBoard, aby zobaczyć, jak metryki zmieniają się w każdej epoce i śledzić inne wartości skalarne:
%tensorboard --logdir logs/fit
Sprawdź prognozy
Uzyskaj uporządkowaną listę nazw klas z prognoz modelu:
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']
Wykreśl prognozy modelu:
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")
Eksportuj i odśwież swój model
Teraz, po wytrenowaniu modelu, wyeksportuj go jako SavedModel, aby użyć go później.
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'
Potwierdź, że możesz ponownie załadować SavedModel i że model jest w stanie wyprowadzić te same wyniki:
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")
Następne kroki
Możesz użyć SavedModel, aby załadować w celu wnioskowania lub przekonwertować go na model TensorFlow Lite (do uczenia maszynowego na urządzeniu) lub model TensorFlow.js (do uczenia maszynowego w JavaScript).
Odkryj więcej samouczków , aby dowiedzieć się, jak używać wstępnie wytrenowanych modeli z TensorFlow Hub w zadaniach związanych z obrazami, tekstem, dźwiękiem i wideo.