Автор: Тинси Джон Перуманур.

Введение в VGG16

VGG16 — это простая и широко используемая архитектура сверточной нейронной сети (CNN), используемая для ImageNet, крупного проекта визуальной базы данных, используемого в исследованиях программного обеспечения для распознавания визуальных объектов. Архитектура VGG16 была разработана и представлена ​​Кареном Симоняном и Эндрю Зиссерманом из Оксфордского университета в 2014 году в их статье «Очень глубокие сверточные сети для крупномасштабного распознавания изображений». «VGG» — это аббревиатура Visual Geometry Group, которая представляет собой группу исследователей из Оксфордского университета, разработавших эту архитектуру, а «16» означает, что эта архитектура имеет 16 уровней (поясняется позже).

Модель VGG16 достигла 92,7% точности теста Top-5 в ImageNet, который представляет собой набор данных из более чем 14 миллионов изображений, принадлежащих к 1000 классам. Это была одна из известных моделей, представленных на конкурс ImageNet Large Scale Visual Recognition Challenge (ILSVRC) в 2014 году. Она улучшила архитектуру AlexNet, заменив большие фильтры размером с ядро ​​(11 и 5 в первом и втором сверточных слоях соответственно). с несколькими фильтрами размера ядра три × три один за другим. VGG16 несколько недель обучался на графических процессорах NVIDIA Titan Black.

VGG16 используется во многих методах классификации изображений для глубокого обучения и популярен благодаря простоте реализации. VGG16 широко используется в обучающих приложениях благодаря своим преимуществам.

VGG16 — это архитектура CNN, которая была использована для победы в конкурсе ImageNet Large Scale Visual Recognition Challenge (ILSVRC) в 2014 году. На сегодняшний день это одна из лучших архитектур машинного зрения.

Архитектура VGG16

Во время обучения входом в коннеты является изображение фиксированного размера 224 x 224 RGB. Вычитание среднего значения RGB, вычисленного в обучающем наборе, из каждого пикселя — единственная предварительная обработка, выполняемая здесь. Изображение проходит через стопку сверточных (конв.) слоев, где фильтры с очень малым полем восприятия: 3 × 3 (что является наименьшим размером для захвата понятия лево/право, вверх/вниз, центр и имеет используется то же эффективное рецептивное поле, что и у одного 7 x 7). Он глубже, имеет больше нелинейностей и меньше параметров. В одной из конфигураций также используются сверточные фильтры 1 × 1, которые можно рассматривать как линейное преобразование входных каналов (с последующей нелинейностью). Шаг свертки и пространственное заполнение conv. входной сигнал слоя фиксируется на 1 пиксель для сверточных слоев 3 x 3, что гарантирует сохранение пространственного разрешения после свертки. Пять слоев максимального объединения, которые следуют за некоторыми сверточными слоями, помогают в пространственном объединении. Максимальное объединение выполняется в окне размером 2×2 пикселя с шагом 2.

Существует три полносвязных (FC) слоя, которые следуют стеку сверточных слоев (они имеют разную глубину в разных архитектурах): первые два имеют по 4096 каналов каждый, третий выполняет 1000-путевую классификацию ILSVRC и, таким образом, содержит 1000 каналов (один для каждого класса). Последний слой — это слой soft-max. Конфигурация полносвязных слоев одинакова во всех сетях.

16-уровневая архитектура VGG показала наилучшие результаты, и, как упоминалось выше, она достигла 7,3% (точность 92,7%) в топ-5 ошибок в ILSVRC — 2014. VGG16 значительно опередил модели предыдущего поколения ILSVRC — 2012 и ILSVRC — 2013.

Архитектура VGG16 изображена на рисунке 1, показанном ниже:

Рисунок 1. Архитектура VGG16

Архитектура VGG16 представляет собой улучшение по сравнению с AlexNet (победитель ILSVRC — 2012), в котором большие фильтры размером с ядро ​​заменены несколькими фильтрами размером с ядро ​​3 x 3 один за другим.

Как обучить VGG16 с нуля?

Процедура обучения ConvNet обычно выполняется путем оптимизации цели полиномиальной логистической регрессии с использованием мини-пакетного градиентного спуска (на основе обратного распространения) с импульсом. Размер партии был установлен равным 256, а импульс равен 0,9. Обучение регулировалось уменьшением веса (штрафной множитель L2 был установлен на 5 · 10−4) и регуляризацией отсева для первых двух полносвязных слоев (коэффициент отсева был установлен на 0,5). Скорость обучения была первоначально установлена ​​на 10-2, а затем уменьшилась в 10 раз, когда точность проверочного набора перестала улучшаться. Всего скорость обучения снизилась в 3 раза, а обучение было остановлено после 370 000 итераций (74 эпохи). Предполагается, что, несмотря на большее количество параметров и большую глубину сверточных сетей, сетям требовалось меньше эпох для сходимости из-за (а) неявной регуляризации, налагаемой большей глубиной и меньшей конверсией. размеры фильтров; (б) предварительная инициализация определенных слоев.

Инициализация весов сети важна, так как плохая инициализация может затормозить обучение из-за нестабильности градиента в глубоких сетях. Чтобы обойти эту проблему, начинается обучение конфигурации A (таблица 1), которая достаточно поверхностна, чтобы ее можно было обучить со случайной инициализацией. Затем при обучении более глубоких архитектур инициализируются первые четыре сверточных слоя и последние три полносвязных слоя со слоями сети А (промежуточные слои инициализировались случайным образом). Скорость обучения для предварительно инициализированных слоев не снижается, что позволяет им изменяться во время обучения. Для случайной инициализации (где применимо) отбираются веса из нормального распределения с нулевым средним значением и дисперсией 10−2. Смещения были инициализированы нулем.

Стоит отметить, что после публикации оригинальной работы, выполненной Кареном Симоняном и Эндрю Зиссерманом, было обнаружено, что можно инициализировать веса без предварительного обучения, используя процедуру случайной инициализации Glorot & Bengio (2010).

Таблица 1. Конфигурации ConvNet (отображается в столбцах). Можно отметить, что глубина конфигураций увеличивается слева (A) направо (E) по мере добавления дополнительных слоев (выделены жирным шрифтом). Параметры сверточного слоя обозначаются как «conv (размер рецептивного поля) — (количество каналов)». Функция активации ReLU здесь не показана.

Входные изображения ConvNet были случайным образом вырезаны из масштабированных обучающих изображений (одна обрезка на изображение на итерацию SGD) для получения изображений ConvNet фиксированного размера 224 × 224. Чтобы еще больше расширить обучающую выборку, культуры подверглись случайному горизонтальному отражению и случайному сдвигу цвета RGB (Крижевский и др., 2012). Изменение масштаба тренировочного изображения объясняется ниже.

Размер тренировочного изображения:

Пусть S будет наименьшей стороной изотропно масштабированного обучающего изображения, из которого вырезается вход ConvNet (мы также называем S масштабом обучения). В то время как размер обрезки фиксирован на 224 × 224, в принципе S может принимать любое значение не меньше 224: при S = ​​224 обрезка будет захватывать статистику всего изображения, полностью охватывая наименьшую сторону обучающего изображения; для S ≫ 224 кроп будет соответствовать небольшой части изображения, содержащей небольшой объект или часть объекта.

Для установки обучающей шкалы S рассматриваются два подхода. Первый заключается в фиксировании S, что соответствует обучению с одной шкалой (обратите внимание, что содержимое изображения в выбранных культурах может по-прежнему представлять многомасштабную статистику изображения). Для экспериментальной оценки оценку моделей обучают по двум фиксированным шкалам: S = 256 (что широко использовалось в предшествующем уровне техники (Крижевский и др., 2012; Zeiler & Fergus, 2013; Sermanet et al., 2014)) и S = ​​384. Учитывая конфигурацию ConvNet, сеть сначала обучалась с использованием S = 256. Чтобы ускорить обучение сети S = ​​384, она была инициализирована с весами, предварительно обученными с S = 256, и более низким начальным использовалась скорость обучения 10−3.

Второй подход к настройке S — это мультимасштабное обучение, при котором каждое обучающее изображение индивидуально масштабируется путем случайной выборки S из определенного диапазона [Smin, Smax] (использовалось Smin = 256 и Smax = 512). Так как объекты на изображениях могут быть разного размера, полезно учитывать это при обучении. Это также можно рассматривать как увеличение тренировочного набора за счет дрожания масштаба, когда одна модель обучается распознавать объекты в широком диапазоне масштабов. Из соображений скорости обучение многомасштабных моделей выполнялось путем точной настройки всех слоев одномасштабной модели с одинаковой конфигурацией, предварительно обученной с фиксированным S = 384.

Использование предварительно обученной сети

Существует два способа использования предварительно обученной сети: извлечение признаков (с увеличением данных и без него) и точная настройка, оба из которых подробно рассматриваются в следующих разделах.

Модель VGG16 поставляется с предварительно упакованным Keras. Его можно импортировать из модуля keras.applications.

VGG16 уникален тем, что вместо большого количества гиперпараметров он ориентирован на наличие сверточных слоев фильтра 3 x 3 с шагом 1 и всегда использует один и тот же слой заполнения и максимальный слой фильтра 2 x 2 шага. 2. Этому расположению слоев свертки и максимального пула соответствует вся архитектура. В конце концов, у него есть 2 полносвязных (FC) слоя, за которыми следует softmax для вывода. Число 16 в VGG16 означает наличие 16 слоев с весом.

Чтобы полностью реализовать VGG16 с нуля в Keras, мы можем использовать набор данных Dogs vs. Cats, доступ к которому можно получить по ссылке ниже.

https://www.kaggle.com/c/dogs-vs-cats/data

Создание экземпляра модели VGG16:

Сверточная база VGG16 может быть реализована следующим образом:

из keras.applications импортировать VGG16

conv_base = VGG16 (веса = ‘imagenet’,

include_top = Ложь,

input_shape = (150, 150, 3))

В конструктор передаются три аргумента:

  • веса определяют контрольную точку веса, из которой инициализируется модель.
  • include_top относится к включению (или отсутствию) плотно связанного классификатора в верхней части сети. По умолчанию плотносвязный классификатор соответствует 1000 классам из ImageNet, но поскольку он предназначен для использования нативного плотносвязного классификатора (с двумя классами: кошка и собака), его включать не нужно.
  • input_shape — это форма тензоров изображений, которые передаются в сеть. Это необязательный параметр, который, если его не передать, позволяет сети обрабатывать входные данные любого размера.

Подробная информация о сверточной базовой архитектуре VGG16, которая похожа на простые консети, представлена ​​в сводке, показанной ниже:

Стоит отметить, что окончательная карта признаков имеет форму (4, 4, 512). Поверх него наклеен плотносвязный классификатор.

Есть два метода, которыми мы можем исходить отсюда.

  • Первый заключается в запуске сверточной базы над набором данных, записи его выходных данных в массив Numpy на диске, а затем использовании этих данных в качестве входных данных для автономного, плотно связанного классификатора. Это решение является быстрым и дешевым в использовании, поскольку требует запуска сверточной базы только один раз для каждого входного изображения, а сверточная база — безусловно, самая дорогая часть конвейера. Но по той же причине этот метод не позволит использовать аугментацию данных.
  • Расширение текущей модели (conv_base) путем добавления слоев Dense сверху и выполнения всего этого от начала до конца на входных данных. Это позволит использовать аугментацию данных, поскольку каждое входное изображение проходит через сверточную базу каждый раз, когда его видит модель. Но по этой причине эта методика гораздо дороже первой и противоречит тому, что там объясняется.

Оба метода объясняются ниже. Изучение кода, необходимого для настройки первого: запись выходных данных conv_base на ваших данных и использование этих выходных данных в качестве входных данных для новой модели.

Быстрое извлечение признаков без увеличения данных:

Экземпляры ImageDataGenerator запускаются для извлечения изображений в виде массивов Numpy, а также их меток. Функции из этих изображений извлекаются путем вызова метода прогнозирования модели conv_base.

Извлечение признаков с использованием предварительно обученной сверточной базы:

импорт ОС

импортировать numpy как np

из keras.preprocessing.image импортировать ImageDataGenerator

base_dir = '/Users/TJ/Загрузки/cats_and_dogs'

train_dir = os.path.join (базовый_каталог, «поезд»)

validation_dir = os.path.join (базовый_каталог, «проверка»)

test_dir = os.path.join (базовый_каталог, «тест»)

datagen = ImageDataGenerator (масштабирование = 1./255)

размер_пакета = 20

def extract_features (каталог, sample_count):

функции = np.zeros (форма = (sample_count, 4, 4, 512))

метки = np.zeros (форма = (sample_count))

генератор = datagen.flow_from_directory(

каталог,

целевой_размер = (150, 150),

размер_пакета = размер_пакета,

class_mode = «двоичный»)

i = 0

для inputs_batch, labels_batch в генераторе:

features_batch = conv_base.predict (входы_пакет)

функции[i * размер_пакета: (i + 1) * размер_пакета] = набор_функций

этикетки[i * размер_пакета : (i + 1) * размер_пакета] = этикетки_пакета

i += 1

если я * размер_пакета ›= количество_образцов:

ломать

возвращаемые функции, метки

train_features, train_labels = extract_features(train_dir, 2000)

validation_features, validation_labels = extract_features(validation_dir, 1000)

test_features, test_labels = extract_features(test_dir, 1000)

Извлеченные признаки имеют форму (образцы 4, 4, 512). Его необходимо сгладить до (образцы, 8192), как показано ниже, чтобы передать его в плотно связанный классификатор.

train_features = np.reshape(train_features, (2000, 4 * 4 * 512))

validation_features = np.reshape (validation_features, (1000, 4 * 4 * 512))

test_features = np.reshape (test_features, (1000, 4 * 4 * 512))

Плотно связанный классификатор может быть определен как эта точка (обратите внимание на использование отсева для регуляризации) и обучен на только что записанных данных и метках.

импортные модели от keras

из слоев импорта keras

от оптимизаторов импорта keras

модель = модели.Sequential()

model.add(layers.Dense(256, активация = ‘relu’, input_dim = 4 * 4 * 512))

model.add(слои.Dropout(0.5))

model.add(layers.Dense(1, активация = ‘сигмоид’))

model.compile (оптимизатор = оптимизаторы.RMSprop (lr = 2e-5),

потеря = ‘binary_crossentropy’,

метрики = ['acc'])

история = model.fit(train_features, train_labels,

эпох = 30,

размер партии = 20,

validation_data = (validation_features, validation_labels))

Обучение происходит очень быстро, так как нужно иметь дело только с двумя плотными слоями — и поэтому эпоха занимает менее одной секунды даже на процессоре.

Теперь построены кривые потерь и точности во время обучения (см. рисунки 3 и 4).

импортировать matplotlib.pyplot как plt

акк = история.история['акк']

val_acc = история.история['val_acc']

убыток = история.история['убыток']

val_loss = history.history['val_loss']

эпохи = диапазон (1, len (acc) + 1)

plt.plot(эпохи, акк, 'bo', метка = 'Обучение акк')

plt.plot(эпохи, val_acc, 'b', метка = 'Проверка акк')

plt.title («Точность обучения и проверки»)

plt.legend()

plt.figure()

plt.plot (эпохи, потери, «бо», метка = «Потери при обучении»)

plt.plot (эпохи, val_loss, «b», метка = «Потеря проверки»)

plt.title («Потеря обучения и проверки»)

plt.legend()

plt.show()

Листинг 5.18. Определение и обучение плотносвязного классификатора

Листинг 5.19. График результатов

Здесь достигается точность проверки около 90%, что намного лучше, чем с небольшой моделью, обученной с нуля. Но графики также показывают, что переобучение происходит почти с самого начала, несмотря на то, что отсев используется довольно часто. Это связано с тем, что этот метод не использует увеличение данных, что необходимо для предотвращения переобучения с небольшими наборами данных изображений.

Рисунок 3. Точность обучения и проверки для простого извлечения признаков

Рисунок 4. Потери при обучении и валидации для простого извлечения признаков

Извлечение признаков с увеличением данных:

Теперь будет рассмотрен второй метод извлечения признаков, который намного медленнее и дороже, но который позволяет использовать аугментацию данных во время обучения: расширение модели conv_base и запуск ее от начала до конца на входах.

Следует отметить, что этот метод очень дорог, и его следует использовать только при наличии доступа к графическому процессору. В противном случае предыдущая техника — это способ решения проблемы.

Поскольку модели ведут себя так же, как слои, вы можете добавить модель (например, conv_base) в модель Sequential точно так же, как если бы вы добавили слой.

Добавление плотносвязного классификатора поверх сверточной базы:

импортные модели от keras

из слоев импорта keras

модель = модели.Sequential()

model.add(conv_base)

model.add(слои.Flatten())

model.add(layers.Dense(256, активация = ‘relu’))

model.add(layers.Dense(1, активация = ‘сигмоид’))

Теперь модель выглядит так, как показано ниже:

Видно, что сверточная база VGG16 имеет 14 714 688 параметров, что очень много. Классификатор, который добавляется сверху, имеет 2 миллиона параметров.

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

В Keras сеть замораживается, если для ее обучаемого атрибута установлено значение False:

››› print(‘Это количество обучаемых весов’

‘перед замораживанием базы конв:’, len(model.trainable_weights))

Это количество тренируемых весов до заморозки конв базы: 30

››› conv_base.trainable = Ложь

››› print(‘Это количество обучаемых весов’

‘после замораживания конв базы:’, len(model.trainable_weights))

Это количество тренируемых весов после заморозки конв базы: 4

Листинг 5.20. Добавление

На этом шаге будут обучены только веса из двух добавленных слоев Dense. Всего это составляет четыре весовых тензора: по два на слой (основная весовая матрица и вектор смещения). Следует отметить, что для того, чтобы эти изменения вступили в силу, модель должна быть предварительно скомпилирована. Если способность к тренировкам с отягощениями изменяется после компиляции, то модель следует перекомпилировать, иначе эти изменения будут проигнорированы.

Теперь мы можем начать обучение модели с той же конфигурацией расширения данных, которая использовалась в предыдущем примере.

Обучение модели от начала до конца с замороженной сверточной базой:

из keras.preprocessing.image импортировать ImageDataGenerator

от оптимизаторов импорта keras

train_datagen = ImageDataGenerator(

масштабирование = 1./255,

диапазон_вращения = 40,

ширина_сдвига_диапазон = 0,2,

height_shift_range = 0,2,

сдвиг_диапазон = 0,2,

масштаб_диапазон = 0,2,

horizontal_flip = Верно,

fill_mode='ближайший')

test_datagen = ImageDataGenerator (масштабирование = 1./255)

train_generator = train_datagen.flow_from_directory(

train_dir,

целевой_размер = (150, 150),

размер партии = 20,

class_mode = «двоичный»)

validation_generator = test_datagen.flow_from_directory(

валидация_каталог,

целевой_размер = (150, 150),

размер партии = 20,

class_mode = «двоичный»)

model.compile (потеря = ‘binary_crossentropy’,

оптимизатор = оптимизаторы.RMSprop(lr = 2e-5),

метрики = ['acc'])

история = модель.fit_generator(

поезд_генератор,

шагов_за_эпоху = 100,

эпох = 30,

валидация_данные = валидация_генератор,

валидация_шагов = 50)

Результаты снова можно изобразить на графике, как показано ниже (рис. 5 и 6), и увидеть, что точность проверки достигает примерно 96%, что намного лучше, чем было достигнуто с небольшой коннетом, обученным с нуля.

Рисунок 5. Точность обучения и проверки для извлечения признаков с увеличением данных

Рисунок 6. Потеря обучения и проверки для извлечения признаков с увеличением данных

Тонкая настройка

Тонкая настройка модели позволяет повторно использовать ее и дополняет извлечение признаков (показано на рисунке 7).

Рисунок 7. Тонкая настройка последнего блока свертки сети VGG16

При тонкой настройке несколько верхних слоев замороженной модели, используемой для извлечения признаков, размораживаются и совместно обучаются как эти верхние слои, так и вновь добавленная часть модели (полностью подключенный классификатор). Этот процесс получил название «тонкая настройка», поскольку он немного корректирует более абстрактные представления повторно используемой модели, чтобы сделать ее актуальной для рассматриваемой проблемы.

Можно точно настроить только верхние слои сверточной базы после того, как верхний классификатор уже обучен. Это связано с тем, что необходимо заморозить сверточную базу VGG16, чтобы иметь возможность обучить сверху случайно инициализированный классификатор. Сигнал ошибки, распространяющийся по сети во время обучения, будет очень большим, а представления, ранее изученные настраиваемыми слоями, будут уничтожены, если классификатор еще не обучен.

Шаги тонкой настройки сети можно описать следующим образом:

  1. Добавьте пользовательскую сеть поверх уже обученной базовой сети.
  2. Заморозить базовую сеть.
  3. Обучите часть, которая была добавлена.
  4. Разморозьте некоторые слои в базовой сети.
  5. Совместно обучите оба этих слоя и ту часть, которая была добавлена.

Первые три шага уже были выполнены во время извлечения признаков. Чтобы перейти к шагу 4, необходимо разморозить conv_base и заморозить отдельные слои.

Было видно, как выглядит сверточная база в сводке модели, показанной на страницах 4 и 5.

Последние три сверточных слоя точно настроены, и все слои до block4_pool должны быть заморожены, а слои block5_conv1, block5_conv2 и block5_conv3 должны быть обучаемыми.

Мы можем точно настроить больше слоев и всю сверточную базу, но необходимо учитывать следующее:

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

В этом случае хорошей стратегией является тонкая настройка только двух или трех верхних слоев сверточной базы. Чтобы настроить это, начиная с того места, где оно было остановлено ранее, мы выполняем следующую операцию замораживания всех слоев до определенного:

conv_base.trainable = Истина

set_trainable = Ложь

для слоя в conv_base.layers:

если layer.name == ‘block5_conv1’:

set_trainable = Истина

если set_trainable:

слой.trainable = Истина

еще:

слой.trainable = Ложь

Теперь можно приступать к тонкой настройке сети. Это можно сделать с помощью оптимизатора RMSProp, используя очень низкую скорость обучения. Причина использования низкой скорости обучения заключается в том, что величина модификаций, которые вы вносите в представления трех слоев тонкой настройки, должна быть ограничена, поскольку слишком большие обновления могут повредить этим представлениям.

Листинг 5.22. Замораживание всех слоев до определенного o

Точная настройка модели:

model.compile (потеря = ‘binary_crossentropy’,

оптимизатор = оптимизаторы.RMSprop(lr=1e-5),

метрики = ['acc'])

история = модель.fit_generator(

поезд_генератор,

шагов_за_эпоху = 100,

эпохи = 100,

валидация_данные = валидация_генератор,

валидация_шагов = 50)

Нанесение результатов с использованием того же кода построения графика, что и раньше, приводит к рисункам 8 и 9.

Рисунок 8. Точность обучения и проверки для тонкой настройки

Рисунок 9. Потери при обучении и валидации для тонкой настройки

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

Сглаживание графиков (результаты см. на рисунках 10 и 11):

def smooth_curve (точки, коэффициент = 0,8):

сглаженные_точки = []

за точку в баллах:

если сглаженные_точки:

предыдущий = сглаженные_точки[-1]

smoothed_points.append(предыдущий * фактор + точка * (1 — фактор))

еще:

smoothed_points.append(точка)

вернуть сглаженные_точки

plt.plot(эпохи,

smooth_curve(acc), ‘bo’, метка = ‘сглаженное обучение acc’)

plt.plot(эпохи,

smooth_curve(val_acc), ‘b’, label = ‘Сглаженная проверка acc’)

plt.title («Точность обучения и проверки»)

plt.legend()

plt.figure()

plt.plot(эпохи,

smooth_curve(потеря), ‘бо’, метка = ‘Сглаженная потеря при обучении’)

plt.plot(эпохи,

smooth_curve(val_loss), ‘b’, label = ‘Сглаженная потеря проверки’)

plt.title («Потеря обучения и проверки»)

plt.legend()

plt.show()

Листинг 5.24. Сглаживание pl

Рисунок 10. Сглаженные кривые для обучения и проверки точности

для тонкой настройки

Рисунок 11. Сглаженные кривые потерь при обучении и валидации

для тонкой настройки

Можно отметить, что кривая точности проверки выглядит намного чище. В нем можно увидеть приятное абсолютное улучшение точности на 1%, примерно с 96% до более 97%. Также отмечается, что кривая потерь не показывает реального улучшения, а вместо этого ухудшается.

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

Теперь модель можно окончательно оценить на тестовых данных, используя следующий код:

test_generator = test_datagen.flow_from_directory(

test_dir,

целевой_размер = (150, 150),

размер партии = 20,

class_mode = «двоичный»)

test_loss, test_acc = model.evaluate_generator (test_generator, шагов = 50)

print('тестовый акк:', test_acc)

Здесь достигается точность теста 97%. Следует отметить, что этот результат был получен с использованием лишь небольшой части доступных обучающих данных (около 10%), с использованием современных методов глубокого обучения. Существует огромная разница между возможностью тренироваться на 20 000 образцов и на 2 000 образцов!

Сколько слоев в VGG16?

VGG16, как следует из названия, имеет 16 весовых слоев. Он уникален в том смысле, что он имеет сверточные слои фильтра 3 x 3 с шагом 1 и всегда использует один и тот же слой заполнения и максимального пула фильтра 2 x 2 с шагом 2. Это вместо большого количества гиперпараметров. .

16 слоев VGG16 описаны ниже:

1. Свертка с использованием 64 фильтров
2. Свертка с использованием 64 фильтров + максимальное объединение
3. Свертка с использованием 128 фильтров
4. Свертка с использованием 128 фильтров + максимальное объединение
5. Свертка с использованием 256 фильтров
6. Свертка с использованием 256 фильтров
7. Свертка с использованием 256 фильтров + Max-pooling
8. Свертка с использованием 512 фильтров
9. Свертка с использованием 512 фильтров
10. Свертка с использованием 512 фильтров + Max-pool
11. Свертка с использованием 512 фильтров
12. Свертка с использованием 512 фильтров
13. Свертка с использованием 512 фильтров + Max-pool
14. Полностью подключен к 4096 узлам
15. Полностью подключен к 4096 узлам
16. Выходной слой с активацией Softmax с 1000 узлами

Конфигурации VGG16

В приведенной ниже таблице 1 (также показанной в предыдущем разделе как таблица 1) показаны все сетевые конфигурации архитектуры VGG. Эти сети следуют одним и тем же принципам проектирования, но различаются по глубине.

Таблица 1. Конфигурации ConvNet (отображается в столбцах). Можно отметить, что глубина конфигураций увеличивается слева (А) направо (Е) по мере добавления дополнительных слоев (выделены жирным шрифтом). Параметры сверточного слоя обозначаются как «conv (размер рецептивного поля) — (количество каналов)». Функция активации ReLU здесь не показана.

Таблица 2. Количество параметров (в миллионах)

  • В приведенной выше таблице представлено много информации, и ее можно увидеть почти во всех попытках описать VGG.
  • Точка 1 : это сравнительная таблица 6 сетей, на которой от А до Е видно, что сеть становится глубже. Для проверки эффекта было добавлено несколько слоев.
  • Пункт 2. Столбцы легко интерпретировать, поскольку в них подробно объясняется структура каждой сети.
  • Точка 3: этот подход помогает использовать самое простое решение для имеющейся проблемы, а затем постепенно оптимизировать его для решения проблем в будущем.
  • Сеть A: сначала упомяните неглубокую сеть, эта сеть может легко сходиться с ImageNet. А потом?
  • Сеть A-LRN: добавьте что-то, что кто-то еще (AlexNet) экспериментировал и назвал эффективным (LRN), но это кажется бесполезным. А потом?
  • Сеть B. Затем попробуйте добавить 2 слоя. Может показаться, что это эффективно. А потом?
  • Сеть C: добавьте еще два слоя свертки 1 1, и она обязательно сойдется. Эффект вроде лучше. И наконец?
  • Сеть D: измените ядро ​​свертки 1 1 на 3 * 3. Попробуйте. Эффект снова улучшился. Это, кажется, лучший (2014).

Варианты использования и реализация VGG16

Два основных недостатка VGG Net:

  1. Очень медленно тренируется.
  2. Вес сетевой архитектуры сам по себе довольно велик (проблема с диском и пропускной способностью).

Несмотря на это, следующие преимущества перевешивают недостатки.

  1. Его легко реализовать, и он является отличным строительным блоком для учебных целей.
  2. VGG16 можно предварительно обучить в ImageNet.

VGG16 можно использовать для трансферного обучения. Подробная реализация VGG16 с использованием кода Python описана в разделе обучения выше.

Предварительная обработка входного изображения для VGG16:

из keras.preprocessing импортировать изображение

из keras.applications.vgg16 импортировать preprocess_input, decode_predictions

импортировать numpy как np

img_path = ‘/Users/TJ/Downloads/creative_commons_elephant.jpg’

img = image.load_img (img_path, target_size = (224, 224))

x = image.img_to_array(img)# float32 Массив Numpy формы (224, 224, 3)

x = np.expand_dims(x, axis = 0) # Добавляет измерение для преобразования массива в пакет размером (1, 224, 224, 3)

x = preprocess_input(x) # Предварительно обрабатывает пакет (выполняет поканальную нормализацию цвета)

Вывод

VGG16 — это сверточная нейронная сеть, которая является широко используемым практическим методом программного обеспечения для распознавания визуальных объектов. Он имеет множество применений во многих методах классификации изображений глубокого обучения и может быть легко реализован, как описано в разделах выше.

Основные выводы из прошлых разделов:

  • Convnets — лучший тип моделей машинного обучения для задач компьютерного зрения. Его можно обучить с нуля, даже на очень маленьком наборе данных, с приличными результатами.
  • На небольшом наборе данных основной проблемой будет переобучение. Увеличение данных — это мощный способ борьбы с переобучением при работе с данными изображений.
  • Существующую сеть легко повторно использовать в новом наборе данных с помощью извлечения признаков. Это ценный метод для работы с небольшими наборами данных изображений.
  • В дополнение к извлечению признаков можно использовать тонкую настройку, которая адаптирует к новой проблеме некоторые представления, ранее изученные существующей моделью. Это немного повышает производительность.

Теперь у нас есть солидный набор инструментов для решения проблем с классификацией изображений, особенно с небольшими наборами данных.

Основные ссылки:

  1. Карен Симонян и Эндрю Зиссерман, Очень глубокие сверточные сети для крупномасштабного распознавания изображений, arXiv (2014), https://arxiv.org/abs/1409.1556.
  2. Франсуа Шолле, «Глубокое обучение с помощью Python», 2018 г.

https://livebook.manning.com/book/deep-learning-with-python/about-this-book/9.