Классификация изображений с помощью очень глубокой нейронной сети

Наша интуиция может подсказывать, что более глубокие нейронные сети должны улавливать более сложные функции и, таким образом, их можно использовать для представления более сложных функций по сравнению с более мелкими. Должен возникнуть вопрос - эквивалентно ли изучение лучшей сети наложению все большего количества слоев? Каковы проблемы и преимущества этого подхода? Эти вопросы и некоторые другие очень важные концепции обсуждались в статье K. He et al. Deep Residual Learning for Image Recognition. в 2017 году. Эта архитектура известна как ResNet, и многие важные концепции, которые необходимо знать, связанные с Deep Neural Network (DNN), были представлены в этом документе, и все они будут рассмотрены в этом посте, включая реализацию 50-слойной ResNet в TensorFlow 2.0. Что вы можете узнать из этого поста -

  1. Проблема с очень глубокой нейронной сетью.
  2. Математическая интуиция за ResNet.
  3. Остаточная блокировка и пропускное соединение.
  4. Структурирование ResNet и важность свертки 1 × 1.
  5. Реализуйте ResNet с помощью TensorFlow.

Давай начнем!

** Более быстрая версия конвейера классификации изображений с использованием tf.data обсуждается здесь.

Проблема деградации:

Основная мотивация оригинальной работы ResNet заключалась в решении проблемы деградации в глубокой сети. Добавление большего количества слоев в достаточно глубокую нейронную сеть сначала приведет к насыщению точности, а затем точность ухудшится. Он и др. представил следующее изображение поезда и ошибки теста с набором данных Cifar-10 с использованием vanilla net:

Как мы видим, ошибки обучения (слева) и тестирования (справа) для более глубокой сети (56-й уровень) выше, чем для 20-уровневой сети. Больше глубины и с увеличением эпох погрешность увеличивается. Сначала кажется, что с увеличением количества слоев количество параметров увеличивается, поэтому возникает проблема переобучения. Но это не так, давайте разберемся.

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

Математическая интуиция ResNet:

Давайте рассмотрим архитектуру DNN, включая скорость обучения и другие гиперпараметры, которые могут достигать класса функций F. Итак, для всех f∈ F, существуют параметры W, которые мы можем получить после обучения сети для определенного набора данных. Если f * обозначает функцию, которую мы действительно хотели бы найти (результат максимально возможной оптимизации), но если она не находится в пределах F, мы пытаемся найти f1, что является лучшим случаем внутри F. Если мы разработаем более мощную архитектуру G, мы должны достичь лучшего результата g1, который лучше, чем f1 . Но если F ⊈ G, то нет гарантии, что это предположение будет выполнено. Фактически g1 может быть хуже, чем f1, и это проблема деградации. Итак, основной момент заключается в следующем: если более глубокие классы функций нейронных сетей содержат более простые и более мелкие классы сетевых функций, то мы можем гарантировать, что более глубокая сеть увеличит способность обнаруживать особенности исходной неглубокой сети. Это будет так. Более ясно, как только мы представим остаточный блок в следующем разделе.

Остаточный блок:

Идея остаточного блока полностью основана на интуиции, которая была объяснена ранее. Более простая функция (более мелкая сеть) должна быть подмножеством сложной функции (более глубокая сеть), чтобы можно было решить проблему деградации. Давайте рассмотрим ввод x, и желаемое отображение от ввода к выводу обозначено g (x). Вместо этой функции мы будем иметь дело с более простой функцией f (x) = g (x) -x. Затем исходное сопоставление преобразовывается в f (x) + x. В статье ResNet He et al. предположил, что проще оптимизировать остаток f (x), чем сам исходный g. Также оптимизация остатка учитывает тот факт, что нам не нужно беспокоиться об ужасном отображении идентичности f (y) → y в очень глубокой сети. Давайте посмотрим на схему остаточного блока ниже -

Формулировка остаточного обучения гарантирует, что когда тождественные отображения оптимальны (т. Е. g (x) = x), оптимизация приведет к приближению весов функции невязки к нулю. ResNet состоит из множества остаточных блоков, где остаточное обучение адаптируется к каждым нескольким (обычно 2 или 3 уровням) уложенным слоям. Строительный блок показан на рисунке 2, а окончательный результат можно рассматривать как y = f (x, W) + x. Здесь W - веса, которые учатся во время тренировки. Операция f + x выполняется путем быстрого («пропустить» 2/3 слоя) соединения и поэлементного добавления. Это простейший блок, в котором не используются дополнительные параметры для пропуска соединения. Поэлементное сложение возможно только тогда, когда размеры f и x одинаковы, если это не так, тогда мы умножаем входные x матрицей проекции Ws,, чтобы размеры f и x совпадали. В этом случае результат изменится с предыдущего уравнения на y = f (x, W) + Ws * x. Элементы в матрице проекции также можно будет обучать.

Построение ResNet и 1 × 1 Convolution:

Мы построим ResNet с 50 слоями, следуя методу, принятому в исходной статье He. и другие. Архитектура, принятая для ResNet-50, отличается от 34-уровневой архитектуры. Быстрое соединение пропускает 3 блока вместо 2, и приведенная ниже схематическая диаграмма поможет нам прояснить некоторые моменты -

В ResNet-50 уложенные слои в остаточном блоке всегда будут иметь сверточные слои 1 × 1, 3 × 3 и 1 × 1. Свертка 1 × 1 сначала уменьшает размер, затем вычисляются характеристики в узком слое 3 × 3, а затем размер снова увеличивается в следующем слое 1 × 1. Использование фильтра 1 × 1 для уменьшения и увеличения размеров карт признаков до и после слоя узких мест было описано в модели GoogLeNet Szegedy et al. в их Начальной статье. Поскольку в остаточном блоке нет объединяющего слоя, размер уменьшается на свертку 1 × 1 с шагом 2. Имея это в виду, давайте создадим ResNet-50 с использованием TensorFlow 2.0.

Корпус ResNet-50:

Перед кодированием давайте посмотрим на архитектуру ResNet-34, представленную в исходной статье -

Только уровни объединения размещаются в самом начале и перед плотным соединением в конце архитектуры. Чтобы изменить размер в другом месте, используется свертка 1 × 1, как описано в предыдущем разделе. По количеству фильтров и другим параметрам я последовал примеру Keras. Пришло время писать код. Сначала мы определяем простейший блок идентификации, в котором размер ввода не изменяется, а изменяется только глубина, ниже показан блок кода:

Другой остаточный блок будет включать в себя изменение размера входа с использованием свертки 1 × 1 с шагом 2. Таким образом, соединение пропуска также претерпит изменение размера -

Комбинируя эти два остаточных блока, мы можем теперь построить полную сеть ResNet из 50 слоев, как показано ниже -

Используя размер пакета в 64, 160 эпох и увеличение данных, была достигнута точность ~ 85% для обучающих данных и ~ 82% для тестовых данных. Ниже приведены кривые обучения и проверки -

Кроме того, можно построить матрицу путаницы для всех 10 классов в данных Cifar-10.

Обсуждение:

Здесь мы видели один пример реализации ResNet-50 с TensorFlow и обучили модель с использованием данных Cifar-10. Одним из важных моментов обсуждения является порядок Convolution - BatchNorm - Activation, который до сих пор остается предметом обсуждения. Порядок, использованный в исходной статье BatchNorm, многими не считается лучшим. См. Проблему на GitHub здесь. Я рекомендую вам попробовать другие параметры, чем те, которые использовались в записной книжке, чтобы понять их влияние.

Вот несколько важных моментов, которые вы можете вынести из этого:

  1. Различие между деградацией и переобучением и почему деградация происходит в очень глубокой сети.
  2. Использование свертки 1 × 1 для увеличения и уменьшения размеров карт функций.
  3. Как остаточный блок помогает предотвратить проблему деградации?

На этом пока все! Надеюсь, это немного поможет вам и останется сильным !!

P.S: Если вы хотите построить более быстрый конвейер классификации изображений с помощью tf.data, то отметьте этот пост.

Ссылка:

[1] Оригинальная статья ResNet: Kaiming He et al.

[2] Пример реализации Keras.

[3] Алекс Смола: Лекция ResNet об интуиции

[4] Блокнот для используемых кодов: GitHub Link.