Модель InceptionV3 обучалась на очень разных изображениях по сравнению с Fashion MNIST. То, что вы видите в этом уроке, является примером трансферного обучения . Приблизительно в обучении передачи вы можете разделить модель на модуль извлечения признаков и модуль классификации. Цель сверточного и объединяющего слоев состоит в том, чтобы автоматизировать извлечение элементов, чтобы мы могли произвести идеальное преобразование из необработанных пикселей изображения в репрезентативный набор функций, которые хорошо описывают изображения.
Эти изображения затем передаются в модуль классификации, где цель состоит в том, чтобы взять эти признаки и фактически выполнить классификацию. Это цель плотных слоев, которые прикрепляются после свертки и объединения. Также обратите внимание, что модель InceptionV3 обучается на изображениях ImageNet, которые имеют 1000 классов. Чтобы успешно применить ImageNet к набору данных Fashion MNIST, вам нужно будет переобучить плотные слои, чтобы слои извлечения и объединения могли взять элементы, извлеченные из изображений, и выполнить для них классификацию. Поэтому установите include_top=False
как то, что вы сделали, но вам также придется прикрепить несколько плотных слоев и переобучить их. Также убедитесь, что вы указали в последнем слое 10 классов из-за набора данных Fashion MNIST.
Однако некоторые ошибки заключаются в том, что InceptionV3 принимает изображения размером 299 x 299, а Fashion MNIST - 28 x 28. Вам нужно будет изменить размеры изображений, а также искусственно дополнить изображения в третьем измерении, чтобы они были в формате RGB. , Поскольку для перехода от 28 x 28 к 299 x 299 требуется увеличение коэффициента в 10 раз в 10 раз, изменение размера изображения до этого разрешения, вероятно, не будет хорошо восприниматься. InceptionV3 можно загрузить в модель, где вы можете изменить ожидаемый размер входного изображения. К сожалению, для InceptionV3 наименьший размер изображения составляет 75 x 75, поэтому нам придется использовать его, а затем изменить размер до 75 x 75. Чтобы изменить размер изображения, вы можете использовать метод Scikit-images resize
из skimage.transform
. Кроме того, если вы планируете использовать InceptionV3, вам необходимо предварительно обработать входные изображения, как они делали в своей сети перед тренировкой.
Таким образом:
from __future__ import absolute_import, division, print_function
from keras.applications.inception_v3 import InceptionV3
from keras.preprocessing import image
from keras.applications.inception_v3 import preprocess_input # New
from keras.models import Model
from keras.layers import Dense, GlobalAveragePooling2D
from keras import backend as K
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
base_model = InceptionV3(weights='imagenet', include_top=False, input_shape=(75, 75, 3))
# Now add some Dense Layers - let's also add in a Global Average Pooling layer too
# as a better way to "flatten"
x = base_model.output
x = GlobalAveragePooling2D()(x)
# let's add a fully-connected layer
x = Dense(1024, activation='relu')(x)
# and a softmax layer -- 10 classes
predictions = Dense(10, activation='softmax')(x)
# Create new model
model = Model(inputs=base_model.input, outputs=predictions)
# Make sure we set the convolutional layers and pooling layers so that they're not trainable
for layer in base_model.layers:
layer.trainable = False
#Preprocessing
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
train_images = train_images.astype(np.float) / 255.0 # Change
test_images = test_images.astype(np.float) / 255.0 # Change
# Preprocessing the images
from skimage.transform import resize
train_images_preprocess = np.zeros((train_images.shape[0], 75, 75, 3), dtype=np.float32)
for i, img in enumerate(train_images):
img_resize = resize(img, (75, 75), anti_aliasing=True)
img_resize = preprocess_input(img_resize).astype(np.float32)
train_images_preprocess[i] = np.dstack([img_resize, img_resize, img_resize])
del train_images
test_images_preprocess = np.zeros((test_images.shape[0], 75, 75, 3), dtype=np.float32)
for i, img in enumerate(test_images):
img_resize = resize(img, (75, 75), anti_aliasing=True)
img_resize = preprocess_input(img_resize).astype(np.float32)
test_images_preprocess[i] = np.dstack([img_resize, img_resize, img_resize])
del test_images
# Compile the model
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# Train it
model.fit(train_images_preprocess, train_labels, epochs=15)
# Now evaluate the model - note that we're evaluating on the new model, not the old one
test_loss, test_acc = model.evaluate(test_images_preprocess, test_labels)
print('Test accuracy:', test_acc)
Обратите внимание, что мне пришлось изменить ожидаемую форму ввода данных из базовой модели InceptionV3, чтобы она составляла 75 x 75 x 3, а 3 - ожидаемые цветные изображения. Кроме того, мне пришлось преобразовать ваши данные в число с плавающей запятой перед делением на 255, иначе данные по-прежнему будут 8-разрядными целыми числами без знака, поэтому единственными значениями будут 0 или 1, что значительно снизит вашу точность. Кроме того, я создал новые массивы, в которых хранятся RGB-версии изображений, размер которых не только изменен до 75 x 75, но также предварительно обработан с использованием того же метода, который InceptionV3 использует перед тренировкой их изображений. Еще одна вещь, которую я должен упомянуть, это то, что нам нужно установить слои до плотных слоев, чтобы мы не тренировались на них. Мы хотим использовать эти слои для предоставления дескрипторов объектов для изображений, которые закачиваются в плотные слои для выполнения классификации. Наконец, обратите внимание, что метки для обучающих и тестовых данных нумеруются от 0 до 9. Поэтому необходимая функция потерь будет разреженной категориальной кросс-энтропийной, которая предназначена для использования в однозначных метках. Функция категориальной кросс-энтропийной потери предполагает одноразовое кодирование.
Мы наконец-то скомпилировали модель, чтобы мы могли настроить ее для обучения, а затем обучить ее. Наконец, мы оцениваем точность данных теста. Это, конечно, потребует некоторой настройки, особенно количества плотных слоев, которое вы хотите, и количества эпох, которые нужно выбрать для обучения.
Внимание
Изменение размера изображений и создание нового массива для них займет некоторое время, поскольку мы зациклим более 60000 обучающих изображений и 10000 тестовых изображений соответственно. Вы должны быть терпеливы здесь. В целях экономии памяти я удаляю исходные обучающие и тестовые изображения из памяти, чтобы компенсировать предварительно обработанные изображения.
Конечная нота
Поскольку набор данных Fashion MNIST обладает значительно меньшими степенями свободы, чем ImageNet, вы можете получить модель с высокой точностью, используя меньше слоев, чем обычно. База данных ImageNet состоит из изображений, которые имеют различные уровни искажения, ориентации объектов, размещения и размера. Если вы построили модель, состоящую всего из нескольких слоев конвона и пула, в сочетании с уплощением и парой плотных слоев, обучение не только займет меньше времени, но вы получите модель с достойной производительностью.