И начальная, и остаточная сети представляют собой архитектуры SOTA, которые показали очень хорошую производительность при относительно низких вычислительных затратах. Inception-ResNet объединяет две архитектуры для дальнейшего повышения производительности.

Остаточные начальные блоки

  1. За каждым блоком Inception следует слой расширения фильтра
    (свертка 1 × 1 без активации), который используется для увеличения размерности банка фильтров перед добавлением, чтобы соответствовать глубине ввода.
  2. В случае 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