CIFAR10 и много графиков.
Это будет такая в некотором роде техническая запись, где почти совсем не будет теоретических умствований, зато будет много графиков (я очень люблю графики, почти так же как формулы).
Базовым датасетом мы выберем CIFAR10, с одной стороны он уже не такой тривиальный как MNIST и значит на нем можно смотреть на достаточно тонкие вещи, с другой он не такой большой как ImageNet, например, а значит можно провести серию экспериментов даже на лаптопе с крайне слабой видеокартой и не умереть от старости ожидая когда они закончатся.
CIFAR 10
Несколько слов о CIFAR. Этот датасет представляет из себя набор цветных картинок размера 32 на 32 пикселя. Каждой картинке сопоставлен один из десяти классов: самолет, автомобиль, птица, кошка, олень, собака, лягушка, лошадь, корабль, грузовик. Датасет разделен на две части: тренировочная содержит 50’000 изображений (по 5’000 каждого класса), тестовая 10’000. Насколько мне известно на данный момент есть статьи в которых заявляется решение задачи классификации на данном датасете с точностью выше 99.0% (см., например, [1] в которой заявлена точность 99.37%). Но я задачи собрать сеть, которая бы достигла “state of the arts” перед собой в данном случае не ставил. Интересен был на самом деле не абсолютный результат, а относительные изменения при добавлении и удалении разных компонент.
Поскольку я несколько свыкся в TensorFlow в качестве фреймворка, то первым делом запустил скрипт, который скачал и сконвертировал CIFAR10 в любимый формат TF, а именно в TFRecord. Скрипт я брал уже готовый с GitHub возможно не такой свежей версии, которая там сейчас (у меня вроде TF1.10 или TF1.15), но вряд ли в этом скрипте с той поры произошли какие-то кардинальные изменения.
VGG like свёрточная сеть
Нам понадобится сетка(и) для тестов. Мы будем использовать сеть, которая фактически повторяет структуру VGG сетей из статьи [3], но поскольку она не совпадает полностью ни с одной из классических VGG сетей, назовём её VGGLike и будем использовать в двух вариантах: с BN и без. Сеть выглядит следующим образом:
Два варианта будут получаться в зависимости от того добавляем ли мы в свёрточные и полносвязные слои BN перед нелинейностью. В последний полносвязный слой BN не добавляется ни в одном из вариантов (так же как и нелинейность).
Batch Normalization и learning rate
Разбирая Batch Normalization мы говорили, что применение этой методики позволяет более свободно выбирать параметры тренировки, в том числе увеличивать learning rate. Для подтверждения данного факта три графика:
Замечания.
-
В качестве метода оптимизации использовался обычный SGD. Learning rate не изменялся на протяжении тренировки. Никакой аугментации к данным не применялось, т.е. и для тренировки и для тестирования брались полные картинки 32 на 32 пикселя. Использовалась $L^2$ регуляризация с weight decay = 0.0001
-
Ошибка и точность на тренировочном датасете считается на протяжении эпохи по каждому батчу и в конце каждой эпохи усредняется и записывается.
Выводы.
При неизменных остальных параметрах тренировки, сеть с применением BN сходится быстрее. Причем сходится даже при таком LR, при котором сеть без BN не сходится.
Batch Normalization, зашумление и ICS
В статье [2], которую я надеюсь разобрать подробнее, предлагается следующий эксперемент. Давайте после BN и до нелинейности добавим немного шума в наши отклики (алгоритм того как формируется шум, описан в статье [2]), очевидно, после этого ICS увеличится (причём, если наблюдать за гистограммами откликов, увеличится даже относительно варианта без BN), но в [4] успех BN объяснялся именно уменьшением ICS, при использовании BN, посмотрим как всё это скажется на скорости тренировки:
Видно, что вариант с BN и при наличии шума и без него тренируется достаточно быстро и быстрее, чем в случае, когда BN отсутствует. Отсюда возникает идея, что ICS в успехе BN никак не участвует.
Замечание. График точности на тестовом датасете не привожу, очевидно если шуметь во всех слоях на этапе тренировки - результат генерализируется крайне плохо.
Расширение тренировочного датасета
Следующий тест, был крайне прост. Насколько, повлияет на результирующую точность простейшее расширение тренировочного датасета.
Сеть остаётся прежней VGG like с BN, параметры тренировки теже, LR используем равный 0.05. Сравниваем вариант, который тренировался без расширения датасета, с вариантом в котором тренировочные данные подвергались следующим преобразованиям:
-
Картинка из тренировочного набора, расширялась на 4 пикселя по обеим координатам (для расширения пиксели исходной картинки симметрично отображались относительно края).
-
Из полученной на шаге 1 картинки размера 40 на 40 пикселей, брался случайный квадрат 32 на 32.
-
С вероятностью 0.5, полученная картинка отражалась относительно вертикальной оси.
Скорость сходимости несколько уменьшилась, однако, качество на тестовом датасете поднялось с 83%-84% до практически 90%, что является серьезным улучшением.
Замечания.
-
Задачи добиться максимальной точности не стояло. Поэтому использовался SGD для оптимизации и LR в процессе тренировки не менялся.
-
Мы не меняли количество итераций или размер мини-батча.
Искажение датасета
Есть еще набор интересных опытов, которые описаны в статье [5]. В данной заметке мы не будем разбираться с теми выводами, которые делают авторы статьи, а просто попробуем эти эксперименты воспроизвести.
Искажение разметки на классы
Зададимся некоторым числом $p \in [0,1]$ и с вероятностью $p$ для каждого изображения в тренировочном датасете заменим приписанный этому изображению класс на класс равномерно случайно выбранный из всех десяти возможных. На краях мы имеем $p = 0$ - исходный датасет, где все метки классов правильные и $p = 1$ - датасет, где каждому изображению приписан случайный класс. Графики:
Видно, что не смотря на то, что в конечном итоге у нас картинкам приписываются просто случайные классы, сетка всё равно умудряется “втренироваться”, т.е. довести точность на тренировочном датасете практически до 100%. При этом логичным образом на тестовом датасете мы наблюдаем ухудшение качество вплоть до 10% для $p = 1$, т.е. случайной разметки.
Отдельно отметим, что 10% неправильно размеченных картинок уменьшают качество классификатора на тестовых данных в данном случае приблизительно на 7% (мы рассматриваем в обоих случаях классификатор натренированный без аугментации датасета).
Искажение изображений
Теперь займемся порчей картинок. Для этого предлагается три методики:
-
Выберем некоторую случайную перестановку пикселей на изображении, зафиксируем её и применим эту перестановку ко всем изображениям из тренировочного и тестового датасетов. С одной стороны мы таким образом напрочь убьём локальную корреляцию пикселей, для которой мы и прикручиваем свёрточные слои. С другой стороны информацию мы не убиваем (чисто теоретически можно поверить, что сетка “восстановит” пиксели из переставленных а потом уже научится и классы различать).
Важно! графики тестовых ошибок в данном случае будут получаться на изменённом тестовом датасете, где к изображениям применена таже перестановка пикселей, что и в тренировочном датасете.
-
Проделаем с каждым изображением операцию перестановки как в случае 1, но только для каждого изображения будем выбирать свою случайную перестановку пикселей. Т.е. мы опять же сохраняем некоторую информацию об изображении, но существенно меньше чем в случае 1.
-
И наконец, посчитаем для каждого изображения математическое ожидание и дисперсию, а потом сформируем новое изоражение, набирая пиксели как независимые случайные величины из нормального распределения с тем же математическим ожиданием и дисперсией. В данном случае информации об изображении остаётся совсем мало.
В последних двух случаях тестовый датасет мы не меняем. Графики:
И в данном случае, снова сетка “втренировывается” не смотря на то, что исходные изображения искажены. При фиксированной перестановке, скорость сходимости практически такая же как и для случая базового датасета, для случаев когда изображение фактически заменено на случайное, сетка тоже сошлась хотя и несколько медленнее.
В случае фиксированной перестановки пикселей на всех изображениях, в том числе и тестовых, сетке удалось и генерализоваться, т.е. на тестовом наборе классификация существенно лучше (~50%) чем простое угадывание (10%)
И завершая тему с внесением искажений в датасет, посмотрим на график точности на тренировочном наборе (скорость “втренировывания” сети), с разными искажениями. Для искажения разметки берем только случаи $p = 0.5$ и $p = 1$, чтобы не захламлять картину.
И в качестве бонуса точность на тестовом:
Интересно, что если для случая задание случайных классов на тестовом имеем 10% точности, то и при случайной перетасовки пикселей и при гауссовском распределении, сеть на тестовом показывает всё таки качество чуть выше совсем случайного.
Литература
-
A. Kolesnikov, L. Beyer, X. Zhai, J. Puigcerver, J. Yung, S. Gelly, N. Houlsby “Big Transfer (BiT): General Visual Representation Learning”, arXiv:1912.11370v3, 2019
-
Sh. Santurkar, D. Tsipras, A. Ilyas, A. Madry, “How Does Batch Normalization Help Optimization?”, arXiv:1805.11604v5, 2019
-
K. Simonyan and A. Zisserman. “Very deep convolutional networks for large-scale image recognition”, arXiv:1409.1556v6, 2015
-
S. Ioffe, Ch. Szegedy, “Batch Normali;zation: Accelerating Deep Network Training by Reducing Internal Covariate Shift”, arXiv:1502.03167v3, 2015
-
C. Zhang, S. Bengio, M. Hardt, B. Recht, and O. Vinyals. “Understanding deep learning requires rethinking generalization”, arXiv:1611.03530v2