Учебное пособие: введение в новую архитектуру CoordConv Uber и ее приложения

Вступление

В 2018 году Uber AI Labs разработала новый уровень для практиков глубокого обучения: CoordConv. Эта концепция была объяснена и протестирована в их бумагах, а также было предоставлено более простое резюме в форме сообщения в блоге. Оба они очень доступны, и я настоятельно рекомендую их для тех, кто хочет увидеть, как этот слой улучшает производительность по ряду проблем. Однако для целей этого руководства я рассмотрю особенности кода для реализации этого слоя и применим его к трем проблемам, упомянутым в исходной работе. Прежде чем углубиться в это, я дам краткое объяснение того, что такое CoordConv, чтобы вы могли следить за кодом, не читая полностью вышеупомянутую запись в блоге или статью.

Несостоятельность сверток в трех простых задачах

Свертки повсеместны в современных архитектурах глубокого обучения. Одна из их предполагаемых сильных сторон - их трансляционная инвариантность; Независимо от того, где на изображении присутствует элемент, можно применить один и тот же шаблон элемента. Использование одного и того же шаблона функции для всего изображения также помогает уменьшить количество параметров, что упрощает обучение. Однако трансляционная инвариантность не всегда может быть полезной. Как показывают разработчики CoordConv, обычный сверточный подход не может решить 3, казалось бы, простых задачи, которые вращаются вокруг перевода между декартовым пространством и пространством горячих координат:

- Контролируемый рендеринг: учитывая некоторую декартову координату (i, j), выделите патч 9x9 на холсте 64x64 с центром вокруг предоставленной координаты.

- Классификация контролируемых координат: заданная некоторая декартова координата (i, j), предоставьте соответствующее ей горячее векторное представление для вектора размером 4096.

- Контролируемая регрессия: для заданного одноразового вектора длиной 4096 предоставьте его соответствующее декартово представление координат в пространстве 64x64.

Нормальные свертки работают очень плохо; мы рассмотрим некоторые результаты позже.

Слой CoordConv

Предлагаемое решение:

… Позволяет фильтрам знать, где они находятся в декартовом пространстве, путем добавления дополнительных жестко закодированных входных каналов, которые содержат координаты данных, видимых сверточным фильтром.

Для 2D-изображения с I строками и J столбцами добавляются два дополнительных канала функций со следующими записями: для первых каналов 0-я строка содержит только нули, следующая строка содержит только все единицы, а для вторых каналов 0-й столбец содержит только нули, следующий содержит все единицы (то есть предоставляются координаты пикселей). Так выглядят дополнительные каналы на входном слое. Для других слоев в сети количество строк и столбцов будет соответствовать высоте и ширине карты объектов на этом конкретном слое. Таким образом, CoordConv может применяться к любому слою, а не только к входному слою (который на самом деле является единственным, работающим в необработанном пиксельном пространстве). На рисунке 1 ниже представлено визуальное представление CoordConv. Другой канал, который можно ввести, - это расстояние этого конкретного пикселя от центра изображения, представление в полярных координатах.

Рисунок 1 (взято из рисунка 3 исходного документа CoordConv) *: визуальное объяснение того, чем слой correconv отличается от обычного сверточного слоя.

Сохранение преимуществ свертки

Двумя основными преимуществами, полученными от использования сверток, являются уменьшение параметров и параметра трансляции. Добавление дополнительных каналов увеличит количество параметров. Однако, как отмечают в статье авторы:

стандартный сверточный слой с квадратным размером ядра k и с входными каналами c и выходными каналами c 'будет содержать cc'k² weights, тогда как соответствующий слой CoordConv будет содержать веса (c + d) c'k², где d - количество используемых координатных измерений (например, 2 или 3). .

d равно 2, когда мы рассматриваем только декартовы каналы, и 3, когда мы вводим канал полярных координат. Из вышесказанного видно, что увеличение количества параметров управляемо. Кроме того, для тех, кому интересно, авторы описывают способ уменьшения увеличения количества параметров с помощью отдельного фильтра для каналов координат (см. Сноску 2 в исходной статье). Для экспериментов, над которыми мы будем работать, мы будем использовать первый метод, который немного проще реализовать.

Что касается трансляционной инвариантности, важно отметить, что, поскольку мы вводим данные координат через конкатенированные каналы, сверточные фильтры могут научиться игнорировать их, если эти каналы не помогают для задачи, которую пытается решить сеть. Фактически, если сеть научится назначать веса 0 параметрам, взаимодействующим с этими каналами, тогда поведение фильтров будет таким, как если бы мы просто использовали обычные свертки, а не CoordConv. Следовательно, мы можем рассматривать обычный ввод свертки как подмножество CoordConv, которое можно изучить, если это подходит для задачи. Хотя для экспериментов, которые мы рассмотрим, мы сможем увидеть, насколько полезным может быть наличие этих дополнительных каналов, если они требуются для текущей задачи.

Код

Давайте рассмотрим, как можно реализовать CoordConv. Я взял следующее из исходной статьи, но я думаю, что стоит пройтись по различным строкам, чтобы лучше понять, как весь блок в конечном итоге функционирует так, как я описал выше. Кроме того, я внес несколько изменений в общую оболочку по сравнению с тем, что вы могли встретить в статье. Они решили реализовать его как функцию класса, но я обнаружил, что это немного перебор, поэтому я сократил его до простой функции.

Весь код, который я обсуждаю в этой статье, можно найти здесь, моя реализация correconv. Кроме того, этот репозиторий также содержит код для запуска экспериментов для сравнения методов coorconv и non -ordinconv в задачах классификации, регрессии и рендеринга. Не стесняйтесь погрузиться в это и поиграть сами. Если вы заметите какие-либо проблемы, создайте пул реквест, и я позабочусь об этом, как только смогу!

Это может показаться немного устрашающим, но я пройдусь по разным разделам и объясню, что происходит.

Чтобы помочь нам обосновать этот код, предположим, что наш входной тензор имеет форму [8, 28, 30, 3]. Таким образом, это может быть набор из 8 изображений высотой 28 и шириной 30 с 3 цветовыми каналами (например, красным, зеленым, синим).

Получение тензорной информации

Эти начальные строки получают различные измерения тензора: размер пакета, количество строк и количество столбцов.

Массив единиц

Сначала мы создаем массив единиц с формой [8, 28], а затем добавляем дополнительное измерение в конце.

Я думаю, что это, наверное, самый сложный момент, особенно вызов «tile», так что давайте рассмотрим его более подробно.

Во-первых, у нас есть вызов `tf.range (y_dim)`, который создает такой вектор: `[0 1… 29]`. Он просто имеет такое же количество строк, что и y_dim, ширину изображения и одну запись в каждой строке, индекс, обозначающий, в какой строке мы сейчас находимся.

Затем вызов `tf.expand_dims` изменяет этот вектор на` [[0 1… 29]] `: дополнительное измерение вводится спереди, так что теперь форма массива равна` (1, 29) `.

Затем у нас есть вызов tf.tile, на понимание которого мне потребовалось больше всего времени. Мы уже прошли через то, что является первым аргументом в пользу этого звонка. Второй аргумент определяет, сколько раз первый аргумент должен быть повторен (или разбит) вдоль каждой оси.

Итак, по первой оси мы хотим, чтобы первый аргумент (массив `[[0 1… 29]]`) повторял `batch_size_tensor` (здесь 8) раз.

Вдоль второй оси не повторяйте массив. Чтобы понять, как это может повторяться на втором месте, если вместо `1` мы укажем` 2`, то вместе с каждым элементом пакета тензор будет содержать `[[0 1… 29 0 1 .. 29] ] `.

Вызов tf.expand_dims здесь вставляет измерение по оси 1, так что окончательная форма тензора будет `(8, 1, 30)`.

Собираем все вместе

Здесь мы объединяем наши предыдущие тензоры формы `(8, 28, 1)` и `(8, 1 30)`, чтобы получить почти последний канал `(8, 28, 30)`.

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

Масштабирование

Вторая отображает координаты, которые у нас есть, в диапазон `[0, 1]`, а третья строка дополнительно отображает это в `[-1, 1]`. Требуется преобразование в числа с плавающей запятой, потому что до этого момента мы работали с целыми числами, но теперь нам нужны десятичные дроби. Если вы планируете много работать с изображениями, этот фрагмент полезно запомнить, поскольку мы часто хотим, чтобы входные данные сети находились в диапазоне `[-1, 1]`.

Чтобы закончить все это, мы объединяем наш новый x-канал, y-канал и исходный входной тензор.

Я не буду проводить вычисления для y-канала, но, надеюсь, ясно, как это работает.

P.S.

Те из вас, кто просматривает исходный документ и предоставленный им фрагмент кода, могут заметить, что строка, содержащая отображение на `[0, 1]`, имеет небольшую разницу по сравнению с моей. Вместо деления на `(y_dim - 1)` они делят на `(x_dim - 1)`. Поскольку канал состоит из координат от «0» до «y_dim», нам нужно делить на размер «y», а не на «x», поэтому их вычисление неверно! Единственный сценарий, в котором это было бы эквивалентно, - это когда мы работаем с квадратными входами и `y_dim = x_dim`. По совпадению, это вход в большинство их экспериментов, возможно, поэтому эта небольшая ошибка не была обнаружена.

Набор данных

Мы рассмотрим контролируемую визуализацию и контролируемую задачу классификации координат. Обе эти задачи по сути противоположны друг другу и используют один и тот же набор данных * Not-so-Clevr *. Этот набор данных состоит из квадратов 9x9 на полотнах размером 64x64. Каждый квадрат связан с декартовой координатой, центральной точкой квадрата. Основываясь на том, что я упомянул во введении, задачи визуализации включают в себя перевод из декартова координатного пространства на холст 64x64, а задача классификации переводит из холста 64x64 с одним выделенным патчем 9x9 обратно в декартово пространство координат.

Чтобы подчеркнуть простоту своего набора данных, оригинальные авторы отмечают, что большая часть набора данных может быть сгенерирована в двух строках кода:

Хотя в нем всего 2 строки, они довольно упакованы, поэтому я дам краткое объяснение здесь.

Команда `np.eye` создает единичную матрицу размером` 3136x3136`. Если мы рассмотрим каждую строку единичной матрицы, только одна запись будет равна 1, а все остальные - 0. Таким образом, мы можем рассматривать эту матрицу как набор всех горячих векторов для вектора длиной 3136. Команда `np.reshape` берет каждый из наших горячих векторов и преобразует его в массив 56x56x1. Если мы подумаем об этом массиве как о холсте «56x56» и примете во внимание, что каждый из них был преобразован из другого горячего вектора, то мы увидим, что для каждого из 3136 холстов «56x56» будет выделен только один пиксель. в то время как все остальные равны 0.

Затем они используют `np.pad`, чтобы увеличить размер каждого холста. Первый и последний параметры `(0,0)` указывают, что не должно быть никаких отступов в первом измерении (размер 3136) или последнем (размер 1). Два средних элемента `(4,4)` дополняют два других измерения четырьмя нулями с каждой стороны, чтобы получившийся массив теперь имел форму `(3136, 64, 64, 1)`. Возвращаясь к идее холстов, теперь каждая из 3136 записей представляет собой холст размером «64x64» с единственной записью, выделенной на меньшей сетке «56x56».

Приведенная ниже двухмерная свертка TensorFlow применяет фильтр «9x9» из единиц к каждому пикселю каждого холста. Всякий раз, когда он встречает 0 на холсте, ничего не меняется, но когда он встречает единственную выделенную 1 на холсте, теперь формируется сетка «9x9» из единиц, центрированная вокруг исходной 1. Таким образом, мы получаем участки «9x9» на холсте. из `64x64`.

Наряду с этим для экспериментов также требуется набор декартовых координат, но код для этого намного проще, поэтому я не буду вдаваться в подробности здесь.

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

- Равномерно: 80% примеров выбираются случайным образом для включения в обучающий набор, а оставшиеся 20% назначаются для тестового набора.

- Квадрант: данные разбиты на 4 квадранта. 3 квадранта назначаются обучающему набору, а оставшийся квадрант является набором тестов.

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

Архитектура для каждой задачи

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

Классификация координат с учителем

Детали архитектуры моделей, используемых для классификации, представлены в первом разделе дополнительных материалов к исходной статье. Для эксперимента с использованием обычных сверток входом в сеть является пара декартовых координат, и затем к ним применяется серия транспонированных сверток для увеличения масштаба до карты 64x64 с выделенным одним пикселем. При использовании слоя CoordConv ввод декартовых координат разбивается на мозаику для создания сетки 64x64, слой CoordConv добавляется к этой карте функций, а затем применяется серия сверток для создания сетки 64x64 с однопиксельной сеткой. выделено. Во всех случаях используется кросс-энтропийная потеря.

Один аспект этой установки, который сначала смутил меня, заключался в том, почему в одном подходе использовались транспонированные свертки, а в другом - обычные. Прежде чем сесть, чтобы хорошенько обдумать это, я попытался разбить декартовы координаты, чтобы создать сетку `64x64`, НЕ добавляя слой CoordConv, а затем применил обычные свертки, чтобы посмотреть, что произойдет. Что происходит в этом сценарии, так это то, что каждая часть входных данных, на которую смотрят сверточные фильтры, абсолютно одинакова, и, следовательно, эту борьбу чрезвычайно сложно изучить. Однако при использовании транспонированных сверток для увеличения декартовых координат до сетки «64x64» каждый элемент сетки немного отличается, и это способствует лучшему обучению. Эту проблему не нужно решать при использовании слоя CoordConv, потому что в этом сценарии добавленные карты функций обеспечивают различия по сетке.

Контролируемая регрессия

Детали архитектуры моделей, используемых для регрессии, представлены в третьем разделе дополнительных материалов к исходной статье. Интересно отметить, что при использовании CoordConv сеть значительно проще и применима как к равномерному, так и к тестируемому разделению. Однако необходимо было разработать две разные архитектуры, полагаясь на обычные свертки, и авторы отмечают, что, хотя сеть для равномерного разделения была достаточно устойчивой к изменениям гиперпараметров, сеть для разделения на квадранты была деликатной в отношении гиперпараметров. Это еще раз подчеркивает неспособность нормальных сверток научиться правильному обобщению для этой задачи. Для всех архитектур здесь использовались среднеквадратические потери ошибок.

Что касается архитектуры CoordConv, я обнаружил, что существует пара «обязательных» настроек для гиперпараметра, чтобы сеть правильно усвоила задачу. Во-первых, когда авторы говорят об использовании глобального пула на последнем уровне, важно использовать максимальный пул, а не средний пул. Использование последнего приводит к тому, что сеть постоянно предсказывает координату `[31.5, 31.5]`. Проблема не в том, что это поплавок; это можно просто исправить округлением в большую или меньшую сторону. Однако это было предсказание независимо от ввода, и быстрый взгляд показывает, что сеть просто предсказывает «среднюю» координату каждой оси. Я думаю, это связано с тем, что объединение средних значений - это, по сути, принудительный акт инвариантности перевода, и поэтому специфичность, предоставляемая CoordConv, теряется. Другой необходимый мне гиперпараметр - это достаточно высокая скорость обучения. Если бы я использовал значение, скажем, «1e-4», сеть снова имела бы ту же проблему с предсказанием. В данном случае я постулирую, что эти прогнозы являются частью локального минимума, из которого трудно выйти при более низких темпах обучения. Скорость обучения «1e-3» или даже «1e-2» позволяла сети делать правильные прогнозы. Еще один аспект, который мог привести к этой ловушке, - это слишком долгие тренировки. Как для равномерного, так и для квадрантного разбиения я обнаружил, что почти идеальные прогнозы были сделаны в пределах 5–10 эпох. Более продолжительное обучение заставило сеть снова начать предсказывать среднюю пару координат. Я бы предположил, что этот конкретный хороший, локальный минимум не очень велик, и дальнейшее обучение с высокой скоростью обучения вынуждает сеть перейти к другому плохому, локальному минимуму, от которого труднее отказаться.

Контролируемый рендеринг

Для этой задачи архитектуры, используемые при работе с обычными свертками и версиями CoordConv, очень похожи на их контролируемую классификацию координат. Основное отличие состоит в том, что на каждом этапе используется больше каналов. Кроме того, вместо использования стандартной потери кросс-энтропии, когда для выделения нацелен только один пиксель, задачи рендеринга использовали потерю кросс-энтропии на каждый пиксель, что позволило выделить сетку «9x9».

Полученные результаты

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

Для каждой задачи мы сравним результаты использования обычных сверток и включения карт CoordConv как для равномерного, так и для квадрантного разбиения. Для всех задач использовался пакет размером 32.

Классификация координат с учителем

CoordConv

Деконв

Контролируемая регрессия

CoordConv

Конв.

Обсуждение: классификация и регрессия

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

Контролируемый рендеринг

Для этих экспериментов, вместо того чтобы рассматривать точность, более полезен визуальный осмотр.

Для обоих разделений данных я использовал одни и те же гиперпараметры как для методаordinconv, так и для метода deconv. Вот настройки:

У каждого разделения данных есть свои уникальные примеры, но одни и те же примеры использовались как для метода correconv, так и для метода deconv.

Единое разделение данных, примеры обучения:

Единое разделение данных, примеры тестирования:

Разделение данных по квадрантам, примеры обучения:

Разделение данных по квадрантам, примеры тестирования:

Деконв

Единое разделение данных, примеры обучения:

Единое разделение данных, примеры тестирования:

Разделение данных по квадрантам, примеры обучения:

Разделение данных по квадрантам, примеры тестирования:

Обсуждение: Рендеринг

Результаты здесь оказались не такими, как я ожидал. Основываясь на производительности других задач и результатах, представленных в исходной статье, я подумал, что смогу достичь почти идеальной производительности в этом случае с помощью correconv, но, как вы можете видеть сверху, это было не так, особенно в квадрантный тест сплит.

Однако я заметил одну вещь: когда я прекратил обучение методам согласования, потери все еще уменьшались, хотя и очень медленно. Следовательно, я предполагаю, что при большем количестве шагов обучения или лучшем расписании обучения метод Coordconv может отображать гораздо более чистые блоки.

Однако если мы посмотрим на результаты методов deconv, есть некоторые свидетельства того, что дополнительное обучение не поможет. Для равномерного разделения данных мы видим, что рамки имеют очень беспорядочные границы даже во время обучения. Плохая тренировка не обнадеживает, когда мы действительно заинтересованы в достижении хороших результатов теста. Если мы рассмотрим разбиение на квадрант, производительность на обучающем подмножестве почти идеальна, даже лучше, чем у метода correcconv. Однако это резко контрастирует с производительностью тестового подмножества. Это указывает на то, что модель использовала свою способность, чтобы соответствовать обучающему подмножеству. Больше тренировок, скорее всего, только усугубит эту проблему.

Обсуждение

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

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

Имейте в виду, что correconv дает больше преимуществ для задач, которые можно выполнить с большим количеством локализованной информации и меньшей инвариантностью перевода. Тем не менее, способ использования correcconv означает, что сеть может решить, насколько важны функцииordinconv.

Заключение

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

использованная литература

[1] Лю Р., Леман, Дж., Молино, П., Сучок, Ф.П., Франк, Э., Сергеев, А. и Йосински, Дж., 2018. Интригующий сбой сверточных нейронных сетей и CoordConv. Решение. Препринт arXiv arXiv: 1807.03247 .

[2] Сообщение в блоге Uber: Интригующий провал сверточных нейронных сетей и решения CoordConv

[3] Вскрытие статьи о глубоком обучении

Об авторе

Эшвин Д. Д’Круз - инженер по машинному обучению в Calipsa. Он имеет степень магистра в области машинного обучения, речи и языковых технологий.

Спасибо за прочтение! Если вам понравилось это руководство, мы будем признательны за вашу поддержку, нажав кнопку хлопка (👏🏼) ниже или поделившись этой статьей, чтобы ее могли найти другие.

Следите за нашими предстоящими публикациями и руководствами по Data Science! Плотный график? Подпишитесь на нашу двухнедельную рассылку новостей ниже, чтобы получать наши сообщения прямо на ваш почтовый ящик.

Нажмите здесь, чтобы подписаться

Дополнительные уроки для отработки навыков:

- Введение в импутация отсутствующих данных
- Шесть проектов Data Science для расширения ваших навыков и знаний
- Модульное тестирование с PySpark
- Настройка гиперпараметров в XGBoost
- Начало работы с XGBoost