Список работ

Загрузка и корректировка модели нейронной сети

Содержание

Введение

Обучение глубоких нейронных сетей требует значительных вычислительных ресурсов. Поэтому понятно желание использовать ранее обученные и сохраненные модели нейронных сетей для решения текущих задач. Keras позволят не только работать с загруженными моделями, но и выполнять их модификацию.
Сохранение модели или ее весов можно выполнять как после завершения обучения нейронной сети, так и в процессе ее обучения.
Cохранение модели или ее весов в процессе обучения в Keras обеспечивает функция обратного вызова ModelCheckpoint, например:

import keras.callbacks as cb
callbacks = []
# Обеспечим сохранение обученной модели в файлы вида filesToSave
filesToSave = 'weights.{epoch:03d}-{val_acc:.2f}.hdf5'
print('Сохраняем веса + ' в файлы вида ' + filesToSave)
# Сохраняем только веса (save_weights_only = True)
# Сохраняем веса, если наблюдается рост val_acc (save_best_only = True)
checkpoint = cb.ModelCheckpoint(filesToSave, monitor = 'val_acc', verbose = 0,
        save_weights_only = True, save_best_only = True, mode = 'max', period = 1)
callbacks.append(checkpoint)
# Обучение нейронной сети
history = model.fit(<другие параметры метода fit>, callbacks = callbacks)

Приведенный код обеспечит сохранение весов модели (поскольку save_weights_only = True) при каждом улучшении наблюдаемой метрики (задается параметром monitor).
Лучшее решение выбирается по значению критерия val_acc – точность классификации оценочных данных.
Модель нейронной сети после завершения ее обучения сохранит метод save, например:

model.save('G:\\AM\\mnist.h5')

Загрузку модели выполнит метод load_model, например:

from keras.models import load_model
#
fileModelToLoad = 'G:/AM/mnist.h5'
print('Загрузка модели из файла ' + fileModelToLoad)
model = load_model(fileModelToLoad)

Загруженную модель можно использовать сразу для решения задач классификации, можно выполнить ее дополнительно обучить, не внося изменений, а также можно прежде изменить, а затем обучить либо всю модель, либо часть, например, только модифицированные и/или добавленные компоненты модели.
Слой L загруженной модели не будет обучаться (не будут меняться его веса), если в программе до начала обучения указать:

L.trainable = False

Список слоев модели содержит ее свойство layers:

layers = model.layers

Все слои, кроме входного, можно получить, например, в следующем цикле:

for L in layers[1:nL - 3]:
    L_nm = L.name
    print(L_nm)

Используя этот цикл, можно собрать модифицированную модель, выполнить ее обучение и при получении приемлемого результата использовать модель по назначению.

Правка загруженной модели

В приводимой ниже программе загружается модель, обученная на MNIST, и затем выполняется попытка улучшить модель. Загруженная модель имеет следующие слои (перед типом слоя указывается его имя, список слоев возвращает метод model.summary()):

Форма входа (28, 28, 1). На последнем слое в загруженной модели применена функция активации Sigmoid.
Новая модель получается в результате замены трех последних слоев на аналогичные, но с другими значениями параметров:

  1. Включаются все слои прежней модели, кроме трех последних – это слои с именами dense_2, dropout_3 и dense_3.
  2. Все включенные в модель в п. 1 слои помечаются как необучаемые.
  3. Добавляется полносвязный слой с размером выхода, равным 32 (вместо 64) и функцией активации Linear.
  4. Добавляется слой прореживания с параметром rate = 0.15 (вместо 0.35).
  5. Добавляется полносвязный, классифицирующий, слой с размером выхода, равным 10 (число классов в MNIST), и функцией активации Softmax вместо Sigmoid.

Далее модель компилируется, и на MNIST обучаются только два ее последних полносвязных слоя (слои прореживания не обучаются, поскольку имеют нулевое число параметров).
Собранная модель имеет 912'132 параметра и только 19'562 из них являются обучаемыми.
Загрузку прежней модели, сборку и компиляцию новой обеспечивает следующий код:

from keras.models import load_model
import keras.losses as ls
#
fileModelToLoad = 'G:/AM/emnist.h5'
print('Загрузка модели из файла ' + fileModelToLoad)
model = load_model(fileModelToLoad)
# Сборка модели
layers = model.layers # Список слоев загруженной модели
nL = len(layers) # Число слоев
inp = layers[0] # Входной слой
# Форму входа возьмем из свойства batch_input_shape
input_shape = inp.batch_input_shape # (None, 28, 28, 1)
input_shape = input_shape[1:] # (28, 28, 1)
# Входной слой нужно задать явно (его нельзя взять из прежней модели)
inp = Input(input_shape)
x = inp
# Берем из прежней модели все слои, кроме трех последних
for L in layers[1:nL - 3]:
    L_nm = L.name
    print(L_nm)
    # Нужно дать слою новое имя
    # В противном случае при добавлении слоев будет нарушена
    # уникальность их имен
    L.name = L_nm + '_m'
    # Помечаем слой как необучаемый
    L.trainable = False
    x = L(x)
# Добавляем к слоям, взятым из прежней модели, три слоя
x = Dense(32, activation = 'linear')(x)
x = Dropout(0.15)(x)
output = Dense(10, activation = 'softmax')(x)
# Model – конструктор модели
model = Model(inputs = inp, outputs = output)
# Вывод сведений о слоях модели
model.summary()
# Компиляция модели
loss = ls.mean_squared_logarithmic_error
model.compile(optimizer = 'Adam', loss = loss, metrics = ['accuracy'])

Далее загружаются данные MNIST (x_train, y_train – обучающие изображения и их метки; x_test, y_test – проверочные изображения и их метки) и выполняется обучение модели, а точнее двух ее последних полносвязных слоев:

history = model.fit(x_train, y_train, batch_size = 256, epochs = 120,
                    verbose = 2, validation_data = (x_test, y_test))

Помимо изменения структуры модели, в методе compile можно указать иные оптимизатор и функцию потерь. Если выбрать функцию потерь binary_crossentropy, то для получения верного значение точности классификации наряду с метрикой accuracy следует использовать метрику categorical_accuracy:

import keras.losses, keras.metrics
loss = keras.losses.binary_crossentropy
metrics = ['accuracy', keras.metrics.categorical_accuracy]
model.compile(optimizer = 'Adam', loss = loss, metrics = metrics)

Заключение

Обученные модели нейронных сетей широко представлены в открытом доступе. В частности, работая с Keras, можно загрузить следующие обученные на ImageNet модели глубоких нейронных сетей [1]:

Набор данных ImageNet [2] создан в рамках проекта ImageNet Large Scale Visual Recognition Challenge (широкомасштабное распознавание изображений ImageNet), цель которого – стимулировать разработку методов классификации, распознавания изображений и других методов машинного зрения. Набор данных ImageNet постоянно расширяется. Вот имена некоторых имеющихся в ImageNet классов:

Источники

  1. Keras Documentation. Applications. [Электронный ресурс] URL: https://keras.io/applications/ (дата обращения: 01.11.2019).
  2. ImageNet. Large Scale Visual Recognition Challenge 2014 (ILSVRC2014). [Электронный ресурс] URL: http://www.image-net.org/challenges/LSVRC/2014/browse-synsets (дата обращения: 01.11.2019).

Список работ

Рейтинг@Mail.ru