Посмотреть на TensorFlow.org | Запустить в Google Colab | Посмотреть на GitHub | Скачать блокнот | См. модель концентратора TF |
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
Вы начнете с использования модели классификатора, предварительно обученной на наборе эталонных данных 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:
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
, которые вы должны использовать при загрузке данных. Заинтересованные читатели могут узнать больше о них, а также о том, как кэшировать данные на диск и о других методах, в руководстве по повышению производительности с помощью API tf.data .
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")
Экспортируйте и перезагрузите модель
Теперь, когда вы обучили модель, экспортируйте ее как 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")
Следующие шаги
Вы можете использовать SavedModel для загрузки для логического вывода или преобразовать ее в модель TensorFlow Lite (для машинного обучения на устройстве) или в модель TensorFlow.js (для машинного обучения в JavaScript).
Откройте для себя дополнительные руководства , чтобы узнать, как использовать предварительно обученные модели из TensorFlow Hub для задач с изображениями, текстом, аудио и видео.