Введение в VGGNet
Полное название VGG — Visual Geometry Group, которая принадлежит Департаменту науки и техники Оксфордского университета. Он выпустил серию сверточных сетевых моделей, начиная с VGG, которые можно применять для распознавания лиц и классификации изображений, от VGG16 до VGG19. Первоначальная цель исследования VGG глубины сверточных сетей — понять, как глубина сверточных сетей влияет на точность и правильность классификации и распознавания крупномасштабных изображений. -Deep-16 CNN), чтобы углубить количество сетевых слоев и избежать слишком большого количества параметров, во всех слоях используется маленькое ядро свертки 3x3.
Структура сети
- На входе 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
- Используется меньшее ядро свертки 3*3 и более глубокая сеть. Стек из двух ядер свертки 3*3 относится к полю зрения ядра свертки 5*5, а стек из трех ядер свертки 3*3 эквивалентен полю зрения ядра свертки 7*7. Таким образом, может быть меньше параметров (3 штабелированные структуры 3 * 3 имеют только 7 * 7 структурных параметров (3 * 3 * 3) / (7 * 7) = 55%); с другой стороны, их больше. Нелинейное преобразование увеличивает способность CNN изучать функции.
- В сверточной структуре VGGNet введено ядро свертки 1*1. Не затрагивая входные и выходные размеры, вводится нелинейное преобразование для увеличения выразительной силы сети и уменьшения объема вычислений.
- Во время обучения сначала обучите простую (низкоуровневую) сеть 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)