И начальная, и остаточная сети представляют собой архитектуры SOTA, которые показали очень хорошую производительность при относительно низких вычислительных затратах. Inception-ResNet объединяет две архитектуры для дальнейшего повышения производительности.
Остаточные начальные блоки
- За каждым блоком Inception следует слой расширения фильтра
(свертка 1 × 1 без активации), который используется для увеличения размерности банка фильтров перед добавлением, чтобы соответствовать глубине ввода. - В случае Inception-ResNet пакетная нормализация используется только поверх традиционных слоев, но не поверх суммирования.
Масштабирование остатков
По словам авторов, если количество фильтров превышало 1000, остаточные варианты начинали демонстрировать нестабильность, и сеть просто «умирала» на ранней стадии обучения, а это означает, что последний слой перед средним объединением начал давать только нули после нескольких десятки тысяч итераций. Этого нельзя было предотвратить ни снижением скорости обучения, ни добавлением дополнительной пакетной нормализации к этому слою.
По их словам, уменьшение остатков перед добавлением их к предыдущей активации слоя, похоже, стабилизировало обучение. Для масштабирования остатков были выбраны коэффициенты масштабирования от 0,1 до 0,3.
Это изображение было взято отсюда.
Создание сети
Импорт необходимых библиотек
import numpy as np import pandas as pd import tensorflow as tf from tensorflow import keras from tensorflow.keras import backend from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, GlobalAveragePooling2D, BatchNormalization from tensorflow.keras.layers import Dense, Dropout, Flatten, Activation, Concatenate, Lambda from tensorflow.keras.models import Model from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint from tensorflow.keras.optimizers import Adam from tensorflow.keras import regularizers, activations import os from sklearn.utils import shuffle from sklearn.metrics import classification_report, confusion_matrix, roc_curve, auc from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt #import itertools #import shutil %matplotlib inline
Предварительная обработка изображений
def random_crop(img, random_crop_size): # Note: image_data_format is ‘channel_last’ h, w = img.shape[0], img.shape[1] dy, dx = random_crop_size x = np.random.randint(0, w — dx + 1) y = np.random.randint(0, h — dy + 1) return img[y:(y+dy), x:(x+dx), :] def crop_generator(batches, crop_length): “””Take as input a Keras ImageGen (Iterator) and generate random crops from the image batches generated by the original iterator. “”” sz = crop_length while True: batch_x, batch_y = next(batches) batch_crops = np.zeros((batch_x.shape[0], sz, sz, 3)) for i in range(batch_x.shape[0]): batch_crops[i] = random_crop(batch_x[i], (sz,sz)) yield (batch_crops, batch_y) tr_datagen = ImageDataGenerator(rescale=1.0/255, horizontal_flip=True, vertical_flip=True) ts_datagen = ImageDataGenerator(rescale=1.0/255) train_gen = tr_datagen.flow_from_directory(train_path, target_size=(IMAGE_SIZE,IMAGE_SIZE), batch_size=train_batch_size, class_mode=’categorical’) tr_crops = crop_generator(train_gen) val_gen = val_datagen.flow_from_directory(valid_path, target_size=(IMAGE_SIZE,IMAGE_SIZE), batch_size=val_batch_size, class_mode=’categorical’) val_crops = crop_generator(val_gen) #Note: shuffle=False causes the test dataset to not be shuffled test_gen = ts_datagen.flow_from_directory(test_path, target_size=(IMAGE_SIZE,IMAGE_SIZE), batch_size=1, class_mode=’categorical’, shuffle=False) #ts_crops = crop_generator(test_gen)
Сверточный блок
Начальный блок ResNet A
Начальный блок ResNet B
Начальный блок ResNet C
Стволовой блок
Сеть Inception-ResNet
Построение модели
model = Model(img_input,x,name=’inception_resnet_v2')
Резюме модели
model.summary()
Сохранить модель как ".png"
from tensorflow.keras.utils import plot_model from IPython.display import SVG plot_model(model, to_file=’model_plot.png’, show_shapes=True, show_layer_names=True)
Настройте модель для обучения
model.compile(Adam(lr=0.0001), loss=’categorical_crossentropy’, metrics=[‘accuracy’])
Модель Checkpoint
filepath = “model.h5” checkpoint = ModelCheckpoint(filepath, monitor=’val_acc’, verbose=1, save_best_only=True, mode=’max’)
Ранняя остановка
early = EarlyStopping(monitor="val_loss", mode="min", patience=4, restore_best_weights=True) callbacks_list = [checkpoint, early]
Обучение модели
history = model.fit_generator(train_gen, steps_per_epoch=train_steps, validation_data=val_gen, validation_steps=val_steps, epochs=20, verbose=1, callbacks=callbacks_list)
Построение статистики тренировок
# Training plots epochs = [i for i in range(1, len(history.history['loss'])+1)] plt.plot(epochs, history.history['loss'], color='blue', label="training_loss") plt.plot(epochs, history.history['val_loss'], color='red', label="validation_loss") plt.legend(loc='best') plt.title('training') plt.xlabel('epoch') plt.savefig(TRAINING_PLOT_FILE, bbox_inches='tight') plt.show() plt.plot(epochs, history.history['acc'], color='blue', label="training_accuracy") plt.plot(epochs, history.history['val_acc'], color='red',label="validation_accuracy") plt.legend(loc='best') plt.title('validation') plt.xlabel('epoch') plt.savefig(VALIDATION_PLOT_FILE, bbox_inches='tight') plt.show()
Оценка модели
#make sure to load the best model model.load_weights('model.h5') predictions = model.predict_generator(test_gen, steps=num_test_images, verbose=1)
Ссылки
Inception-v4, Inception-ResNet и влияние остаточных соединений на обучение: https://arxiv.org/abs/1602.07261
Обрезка случайного изображения в Keras: Блог JK Jung’s