Введение в VGGNet

Полное название VGG — Visual Geometry Group, которая принадлежит Департаменту науки и техники Оксфордского университета. Он выпустил серию сверточных сетевых моделей, начиная с VGG, которые можно применять для распознавания лиц и классификации изображений, от VGG16 до VGG19. Первоначальная цель исследования VGG глубины сверточных сетей — понять, как глубина сверточных сетей влияет на точность и правильность классификации и распознавания крупномасштабных изображений. -Deep-16 CNN), чтобы углубить количество сетевых слоев и избежать слишком большого количества параметров, во всех слоях используется маленькое ядро ​​свертки 3x3.

Структура сети VGG19

Структура сети

  • На входе VGG установлено изображение RGB размером 224x244. Среднее значение RGB вычисляется для всех изображений на изображении тренировочного набора, а затем изображение вводится в качестве входных данных для сверточной сети VGG. Используется фильтр 3x3 или 1x1 с фиксированным шагом свертки. . Существует 3 полносвязных слоя VGG, которые могут варьироваться от VGG11 до VGG19 в зависимости от общего количества сверточных слоев + полносвязных слоев. Минимальный VGG11 имеет 8 сверточных слоев и 3 полносвязных слоя. Максимальный VGG19 имеет 16 сверточных слоев. +3 полносвязных слоя. Кроме того, за сетью VGG не следует слой пула за каждым сверточным слоем или всего 5 слоев пула, распределенных по разным сверточным слоям. На следующем рисунке представлена ​​схема структуры VGG:

  • VGG16 содержит 16 слоев, а VGG19 содержит 19 слоев. Ряд VGG точно такой же в последних трех полносвязных слоях. Общая структура включает 5 наборов сверточных слоев, за которыми следует MaxPool. Разница в том, что в пять наборов сверточных слоев включается все больше и больше каскадных сверточных слоев.

  • Каждый сверточный слой в AlexNet содержит только одну свертка, а размер ядра свертки составляет 7*7,. В VGGNet каждый слой свертки содержит от 2 до 4 операций свертки. Размер ядра свертки — 3 * 3, размер шага свертки — 1, ядра объединения — 2 * 2, размер шага — 2. Наиболее очевидным улучшением VGGNet является уменьшение размера ядра свертки и увеличение количество слоев свертки.

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

  • Две последовательные свертки 3*3 эквивалентны рецептивному полю 5*5, а три эквивалентны 7*7. Преимущества использования трех сверток 3*3 вместо одной свертки 7*7 двояки: один, включающий три слоя ReLu вместо одного делает функцию принятия решения более дискриминирующей; и два, уменьшающие параметры. Например, вход и выход — это все каналы C. 3 сверточных слоя с использованием 3 * 3 требуют 3 (3 * 3 * C * C) = 27 * C * C, а 1 сверточный слой с использованием 7 * 7 требует 7 * 7 * C * C = 49C * C. Это можно увидеть как применение своего рода регуляризации к свертке 7 * 7, так что она разлагается на три свертки 3 * 3.
  • Слой свертки 1 * 1 предназначен в основном для увеличения нелинейности функции принятия решения, не влияя на восприимчивое поле слоя свертки. Хотя операция свертки 1*1 является линейной, ReLu добавляет нелинейности.

конфигурация сети

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

  • Эта картинка определенно используется при представлении VGG16. Эта картинка содержит много информации. Моя интерпретация здесь может быть ограниченной. Если у вас есть какие-либо добавки, пожалуйста, оставьте сообщение.
  • Номер 1. Это сравнительная таблица шести сетей. От А до Е сеть становится глубже. Для проверки эффекта было добавлено несколько слоев.
  • Номер 2. В каждом столбце подробно объясняется структура каждой сети.
  • Номер 3. Это правильный способ проведения экспериментов, то есть использование простейшего метода для решения проблемы, а затем постепенная оптимизация для возникающих проблем.

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

Обучение

  • Метод оптимизации представляет собой стохастический градиентный спуск SGD + импульс (0,9) с импульсом. Размер партии 256 штук.
  • Регуляризация: используется регуляризация L2, а уменьшение веса составляет 5e-4. Отсев после первых двух полносвязных слоев, p = 0,5.
  • Хотя она глубже и имеет больше параметров, чем сеть AlexNet, мы предполагаем, что VGGNet может сходиться за меньшее количество циклов по двум причинам: во-первых, большая глубина и меньшие свертки обеспечивают неявную регуляризацию; Во-вторых, несколько слоев предварительной подготовки.
  • Инициализация параметров. Для мелкой сети A параметры инициализируются случайным образом, вес w выбирается из N (0, 0,01), а смещение инициализируется равным 0. Затем для более глубоких сетей сначала первые четыре сверточных слоя и три полносвязных слоя инициализируются параметрами сети A. Однако позже было обнаружено, что его также можно инициализировать напрямую без использования предварительно обученных параметров.
  • Чтобы получить входное изображение 224 * 224, каждое масштабированное изображение случайным образом обрезается на каждой итерации SGD. Чтобы улучшить набор данных, обрезанное изображение также случайным образом переворачивается по горизонтали и смещается цвет RGB.

Резюме точек улучшения VGGNet

  1. Используется меньшее ядро ​​свертки 3*3 и более глубокая сеть. Стек из двух ядер свертки 3*3 относится к полю зрения ядра свертки 5*5, а стек из трех ядер свертки 3*3 эквивалентен полю зрения ядра свертки 7*7. Таким образом, может быть меньше параметров (3 штабелированные структуры 3 * 3 имеют только 7 * 7 структурных параметров (3 * 3 * 3) / (7 * 7) = 55%); с другой стороны, их больше. Нелинейное преобразование увеличивает способность CNN изучать функции.
  2. В сверточной структуре VGGNet введено ядро ​​свертки 1*1. Не затрагивая входные и выходные размеры, вводится нелинейное преобразование для увеличения выразительной силы сети и уменьшения объема вычислений.
  3. Во время обучения сначала обучите простую (низкоуровневую) сеть VGGNet A-level, а затем используйте веса сети A для инициализации последующих сложных моделей, чтобы ускорить сходимость обучения.

Некоторые основные часто задаваемые вопросы

В1. Почему 3 свертки 3x3 могут заменить свертки 7x7?

Ответ 1
3 свертки 3x3 с использованием 3 нелинейных функций активации, увеличение возможностей нелинейного выражения, повышение разделимости плоскости сегментации Уменьшение количества параметров . Для ядра свертки каналов C 7x7 содержит параметры, а количество 3-х параметров 3x3 сильно уменьшено.

Вопрос 2. Роль ядра свертки 1 x 1

Ответ 2
Увеличение нелинейности модели без воздействия на рецептивное поле. Намоточная машина 1x1 эквивалентна линейному преобразованию, а нелинейная функция активации играет нелинейную роль. -линейная роль

Вопрос 3. Влияние глубины сети на результаты (в том же году Google также независимо выпустила сеть GoogleNet с глубиной 22 слоя)

Ответ 3
Модели VGG и GoogleNet являются глубокими Малая свертка VGG использует только 3x3, тогда как GoogleNet использует 1x1, 3x3, 5x5, модель более сложная (модель стали использовать большое ядро ​​свертки, чтобы уменьшить расчет последующего машинного слоя)

Реализация кода:

from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.models import Model

import warnings
warnings.filterwarnings("ignore", category=FutureWarning)

_input = Input((224,224,1)) 

conv1  = Conv2D(filters=64, kernel_size=(3,3), padding="same", activation="relu")(_input)
conv2  = Conv2D(filters=64, kernel_size=(3,3), padding="same", activation="relu")(conv1)
pool1  = MaxPooling2D((2, 2))(conv2)

conv3  = Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu")(pool1)
conv4  = Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu")(conv3)
pool2  = MaxPooling2D((2, 2))(conv4)

conv5  = Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu")(pool2)
conv6  = Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu")(conv5)
conv7  = Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu")(conv6)
pool3  = MaxPooling2D((2, 2))(conv7)

conv8  = Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu")(pool3)
conv9  = Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu")(conv8)
conv10 = Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu")(conv9)
pool4  = MaxPooling2D((2, 2))(conv10)

conv11 = Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu")(pool4)
conv12 = Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu")(conv11)
conv13 = Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu")(conv12)
pool5  = MaxPooling2D((2, 2))(conv13)

flat   = Flatten()(pool5)
dense1 = Dense(4096, activation="relu")(flat)
dense2 = Dense(4096, activation="relu")(dense1)
output = Dense(1000, activation="softmax")(dense2)

vgg16_model  = Model(inputs=_input, outputs=output)

# Working with pretrained model


from keras.applications.vgg16 import decode_predictions
from keras.applications.vgg16 import preprocess_input
from keras.preprocessing import image
import matplotlib.pyplot as plt 
from PIL import Image 
import seaborn as sns
import pandas as pd 
import numpy as np 
import os 

img1 = "../input/flowers-recognition/flowers/tulip/10094729603_eeca3f2cb6.jpg"
img2 = "../input/flowers-recognition/flowers/dandelion/10477378514_9ffbcec4cf_m.jpg"
img3 = "../input/flowers-recognition/flowers/sunflower/10386540696_0a95ee53a8_n.jpg"
img4 = "../input/flowers-recognition/flowers/rose/10090824183_d02c613f10_m.jpg"
imgs = [img1, img2, img3, img4]

def _load_image(img_path):
    img = image.load_img(img_path, target_size=(224, 224))
    img = image.img_to_array(img)
    img = np.expand_dims(img, axis=0)
    img = preprocess_input(img)
    return img 

def _get_predictions(_model):
    f, ax = plt.subplots(1, 4)
    f.set_size_inches(80, 40)
    for i in range(4):
        ax[i].imshow(Image.open(imgs[i]).resize((200, 200), Image.ANTIALIAS))
    plt.show()
    
    f, axes = plt.subplots(1, 4)
    f.set_size_inches(80, 20)
    for i,img_path in enumerate(imgs):
        img = _load_image(img_path)
        preds  = decode_predictions(_model.predict(img), top=3)[0]
        b = sns.barplot(y=[c[1] for c in preds], x=[c[2] for c in preds], color="gray", ax=axes[i])
        b.tick_params(labelsize=55)
        f.tight_layout()

#Using pretrained weights

from keras.applications.vgg16 import VGG16
vgg16_weights = '../input/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels.h5'
vgg16_model = VGG16(weights=vgg16_weights)
_get_predictions(vgg16_model)