В этом посте рассматривается процесс внедрения трансферного обучения для классификации изображений. Я буду использовать архитектуру VGG16 с весами imagenet, но этот процесс можно использовать и с другими архитектурами моделей, такими как VGG19, ResNet-50 и т. д.
Первое, что нам нужно сделать, это сделать необходимый импорт. Я буду использовать Keras в этом посте.
from keras.layers import Input from keras.models import Model from keras.applications import VGG16 from keras.layers import Flatten, Dropout, Dense from keras.callbacks import ModelCheckpoint, EarlyStopping
Поскольку настройку данных для обучения и тестирования я описал в предыдущем посте, давайте перейдем к построению и обучению модели. Подход, который я буду использовать здесь, заключается в том, чтобы использовать модель VGG16 для вывода признаков на слои FC для проведения классификации. Для этого мы должны указать, что нам не нужен исходный выходной слой модели VGG16, установив для include_top значение False. input_shape должен быть установлен на любые размеры вашего изображения. В этом случае изображения RGB имеют размер 224x224 пикселя, поэтому форма (224, 224, 3). Если вы не знакомы с тем, как создается эта модель, возможно, вы привыкли настраивать свои модели последовательно. Эта модель настроена с помощью функционального API Keras.
vgg_model = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3)) x = vgg_model.output x = Flatten()(x) # Flatten dimensions to for use in FC layers x = Dense(512, activation='relu')(x) x = Dropout(0.5)(x) # Dropout layer to reduce overfitting x = Dense(256, activation='relu')(x) x = Dense(5, activation='softmax')(x) # Softmax for multiclass transfer_model = Model(inputs=vgg_model.input, outputs=x)
Перед тренировкой всегда полезно изучить структуру вашей сети. Простой способ сделать это в Keras — использовать model.summary(), который даст вам все имя, выходную форму и количество параметров для каждого слоя. Сводка для модели, созданной выше, показана ниже.
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_2 (InputLayer) (None, 224, 224, 3) 0 _________________________________________________________________ block1_conv1 (Conv2D) (None, 224, 224, 64) 1792 _________________________________________________________________ block1_conv2 (Conv2D) (None, 224, 224, 64) 36928 _________________________________________________________________ block1_pool (MaxPooling2D) (None, 112, 112, 64) 0 _________________________________________________________________ block2_conv1 (Conv2D) (None, 112, 112, 128) 73856 _________________________________________________________________ block2_conv2 (Conv2D) (None, 112, 112, 128) 147584 _________________________________________________________________ block2_pool (MaxPooling2D) (None, 56, 56, 128) 0 _________________________________________________________________ block3_conv1 (Conv2D) (None, 56, 56, 256) 295168 _________________________________________________________________ block3_conv2 (Conv2D) (None, 56, 56, 256) 590080 _________________________________________________________________ block3_conv3 (Conv2D) (None, 56, 56, 256) 590080 _________________________________________________________________ block3_pool (MaxPooling2D) (None, 28, 28, 256) 0 _________________________________________________________________ block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160 _________________________________________________________________ block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808 _________________________________________________________________ block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808 _________________________________________________________________ block4_pool (MaxPooling2D) (None, 14, 14, 512) 0 _________________________________________________________________ block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_pool (MaxPooling2D) (None, 7, 7, 512) 0 _________________________________________________________________ flatten_1 (Flatten) (None, 25088) 0 _________________________________________________________________ dense_1 (Dense) (None, 512) 12845568 _________________________________________________________________ dropout_1 (Dropout) (None, 512) 0 _________________________________________________________________ dense_2 (Dense) (None, 256) 131328 _________________________________________________________________ dense_3 (Dense) (None, 5) 1285 ================================================================= Total params: 27,692,869 Trainable params: 27,692,869 Non-trainable params: 0 _________________________________________________________________
Как видно из сводки модели, в части VGG16 нашей модели можно обучить множество параметров. Поскольку эти слои уже предварительно обучены с помощью весов imagenet, их пока не нужно обучать. Вместо этого мы заморозим их, используя приведенный ниже код.
for layer in transfer_model.layers[:19]: layer.trainable = False # Make sure you have frozen the correct layers for i, layer in enumerate(transfer_model.layers): print(i, layer.name, layer.trainable)
Теперь, когда у нас есть модель переноса с замороженными правильными слоями, мы можем скомпилировать и обучить. Я также собираюсь использовать контрольную точку и раннюю остановку обратных вызовов.
custom_model2.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) checkpoint = ModelCheckpoint("VGG16_1.h5", monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1) early = EarlyStopping(monitor='val_acc', min_delta=0, patience=10, verbose=1, mode='auto') model_hist2 = custom_model2.fit_generator( train_generator, steps_per_epoch = train_generator.samples // batch_size, validation_data = validation_generator, validation_steps = validation_generator.samples // batch_size, epochs = epochs, callbacks = [checkpoint, early])
После обучения модель достигла точности проверки 72%. Это немного хуже, чем базовая модель, которую я настроил в первом посте, поэтому в следующих постах я рассмотрю различные архитектуры.