Примеры архитектур сверточных сетей VGG-16 и VGG-19

На этом занятии рассмотрим две довольно популярные архитектуры СНС от компании Visual Geometry Group:

VGG-16 и VGG-19

разработанные для распознавания объектов на изображениях. В 2014-м году сеть VGG-16 на соревнованиях по распознаванию изображений базы ImageNet достигла небывалой на тот момент точности в 92,7%. И по этому показателю почти сравнялась с человеком. Теперь она выложена в открытом доступе (причем, с обученными весовыми коэффициентами), чтобы каждый желающий мог проводить с ней любые эксперименты.

Итак, общая структура сети VGG-16, следующая:

На вход подает полноцветное изображение с тремя каналами: RGB. Затем, оно последовательно проходит через сверточные слои Conv1-1 и Conv1-2, каждый имеет по 64 фильтра с размером ядер 3х3. Далее, операция MaxPooling уменьшает вдвое линейные размеры карт признаков и результат обрабатывается двумя последовательными слоями Conv2-1 и Conv2-2 со 128 фильтрами с тем же размером ядер 3х3. И так далее. Потом через три сверточных слоя все проходит, потом еще через три.  Результирующий тензор размером 7х7х512 подается на полносвязную НС с 4096 нейронами двух скрытых слоев и 1000 нейронами выходного слоя. Число 1000 соответствует количеству классов, на которые эта сеть была обучена.

У вас может возникнуть вопрос: а зачем здесь ставится подряд два, а то и три сверточных слоя? Почему нельзя обойтись одним? На самом деле можно. Вместо первых двух слоев Conv1-1 и Conv1-2 с ядрами 3х3 пикселя можно использовать один эквивалентный слой с ядрами 5х5 пикселей:

Хорошо, но тогда почему бы один такой слой и не использовать вместо двух? Дело в том, что число параметров у ядра 5х5 равно:

(здесь +1 – это биас). А у двух ядер 3х3:

То есть, два подряд идущих сверточных слоя имеют меньше настраиваемых параметров, чем один с ядром 5х5. Это основанная причина их использования в архитектуре сети VGG-16. Я думаю, вам теперь понятна вся структура этой сети. В краткой записи она выглядит так:

VGG-16

VGG-19

input (224x244x3)

conv3-64

conv3-64

conv3-64

conv3-64

maxpool

conv3-128

conv3-128

conv3-128

conv3-128

maxpool

conv3-256

conv3-256

conv3-256

conv3-256

conv3-256

conv3-256

conv3-256

maxpool

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

maxpool

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

maxpool

FC-4096

FC-4096

FC-1000

softmax

Во втором столбце представлена аналогичная архитектура сети VGG-19. Как вы уже догадались, здесь числа 16 и 19 означают общее количество слоев в нейронной сети.

Преимуществом этих сетей является их относительная простота. А недостатком – медленная скорость обучения и большое количество весовых коэффициентов. Если их все сохранить на диск, то получится объем примерно 533 МБ.

Реализация VGG-сетей в Keras

Пакет Keras содержит в своем составе обе сверточные сети: VGG16 и VGG19. Для их подключения в своем проекте нужно обратиться к соответствующим классам по ветке:

  • tf.keras.applications.VGG16 – для сети VGG16;
  • tf.keras.applications.VGG19 – для сети VGG19.

Их синтаксис схож и содержит следующие параметры:

tf.keras.applications.VGG16(
    include_top=True,
    weights="imagenet",
    input_tensor=None,
    input_shape=None,
    pooling=None,
    classes=1000,
    classifier_activation="softmax",
)
  • include_top – использовать ли полносвязные слои (True – да; False – нет);
  • weights – определяет значения весов (по умолчанию берутся обученные на коллекции изображений ImageNet);
  • classes = 1000 – число выходных нейронов;
  • classifier_activation – функция активации для выходных нейронов.

Остальные параметры используются редко и оставляются по умолчанию. При создании экземпляра класса создается заданная модель СНС с VGG структурой.

Давайте для примера воспользуемся этой сетью и выполним распознавание случайно выбранного изображения размером 224x224 пикселей:

import numpy as np
import matplotlib.pyplot as plt
from tensorflow import keras
from google.colab import files
from io import BytesIO
from PIL import Image
 
model = keras.applications.VGG16()
 
uploaded = files.upload()
img = Image.open(BytesIO(uploaded['ex224.jpg']))
plt.imshow( img )
 
# приводим к входному формату VGG-сети
img = np.array(img)
x = keras.applications.vgg16.preprocess_input(img)
print(x.shape)
x = np.expand_dims(x, axis=0)
 
# прогоняем через сеть
res = model.predict( x )
print(np.argmax(res))

Вначале подключаем необходимые пакеты, затем, создаем модели сети VGG16 с параметрами по умолчанию. Загружаем файл изображения.

Здесь метод preprocess_input преобразовывает изображение из формата RGB в формат BGR (на котором обучалась сеть VGG-16) и, кроме того, уменьшает средние значения каждого цветового канала на величины:

(B) 103.939, (G) 116.779 и (R) 123.68

Затем, добавляем нулевую ось, чтобы получить формат входных данных:

(batch_size, height, width, channels)

И пропускаем через НС. Максимальное значение соответствует 817 нейрону, что в соответствии с базой изображений ImageNet, означает

817: 'sports car, sport car'

Полную классификацию можно посмотреть здесь:

https://gist.github.com/yrevar/942d3a0ac09ec9e5eb3a

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

Аналогично можно попробовать сеть VGG19, но это будет уже домашним заданием, для тех, кому интересно провести свои небольшие исследования.

Видео по теме