.. _sec_why-conv: От полносвязных слоёв к свёрткам ================================ До сих пор рассмотренные нами модели остаются подходящим выбором при работе с табличными данными. Под табличными данными мы понимаем данные, представленные в виде строк, соответствующих примерам, и столбцов, соответствующих признакам. При работе с такими данными мы можем предполагать, что искомые закономерности могут включать взаимодействия между признаками, но не делаем никаких априорных предположений о структуре этих взаимодействий. Иногда нам действительно не хватает знаний, чтобы конструировать более сложные архитектуры. В таких случаях многослойный перцептрон может оказаться наилучшим решением. Однако для высокоразмерных перцептивных данных такие сети без структуры могут становиться громоздкими. Например, вернёмся к нашему основному примеру — различению кошек и собак. Предположим, мы тщательно подошли к сбору данных и создали размеченный набор данных из фотографий разрешением один мегапиксель. Это означает, что каждый вход сети имеет миллион измерений. Даже агрессивное сокращение до тысячи скрытых измерений потребовало бы полносвязного слоя с :math:`10^6 \times 10^3 = 10^9` параметрами. Если у нас нет множества видеокарт, таланта к распределённой оптимизации и огромного запаса терпения, обучение параметров такой сети может оказаться невозможным. Внимательный читатель может возразить, что разрешение в один мегапиксель не является необходимым. Однако, даже если мы сможем обойтись ста тысячами пикселей, наш скрытый слой размером 1000 грубо недооценивает количество скрытых единиц, необходимых для обучения качественных представлений изображений, поэтому практическая система всё равно будет требовать миллиардов параметров. Более того, обучение классификатора с подгонкой столь большого числа параметров может потребовать сбора огромного набора данных. И всё же сегодня как люди, так и компьютеры способны довольно хорошо различать кошек и собак, что, казалось бы, противоречит этим интуициям. Это связано с тем, что изображения обладают богатой структурой, которую могут использовать как люди, так и модели машинного обучения. Свёрточные нейронные сети (CNN) — это один из творческих подходов, с помощью которого машинное обучение использует известную структуру природных изображений. Инвариантность -------------- Представим, что мы хотим обнаружить объект на изображении. Логично предположить, что метод распознавания объектов не должен слишком сильно зависеть от точного местоположения объекта на изображении. В идеале наша система должна использовать это знание. Свиньи обычно не летают, а самолеты — не плавают. Тем не менее мы должны уметь опознать свинью, если бы она появилась в верхней части изображения. Здесь мы можем почерпнуть вдохновение из детской игры «Где Уолдо?» (которая, в свою очередь, вдохновила множество реальных аналогов, таких как показанный на :numref:`img_waldo`). Игра состоит из множества хаотичных сцен, переполненных действиями. Уолдо появляется где-то в каждой из них, обычно прячась в каком-нибудь неожиданном месте. Цель читателя — найти его. Несмотря на его характерный наряд, это может оказаться удивительно сложным из-за большого количества отвлекающих факторов. Однако *то, как выглядит Уолдо*, не зависит от *того, где он находится*. Мы могли бы просканировать изображение детектором Уолдо, который присваивал бы оценку каждому фрагменту, указывающую на правдоподобие того, что данный фрагмент содержит Уолдо. На самом деле многие алгоритмы обнаружения объектов и сегментации основаны на этом подходе :cite:`Long.Shelhamer.Darrell.2015`. Свёрточные нейронные сети систематизируют идею *пространственной инвариантности*, используя её для обучения полезным представлениям с меньшим количеством параметров. .. _img_waldo: .. figure:: ../img/waldo-football.jpg :width: 400px Можете ли вы найти Вальдо (изображение предоставлено Уильямом Мерфи (Infomatique))? Теперь мы можем сделать эти интуитивные представления более конкретными, перечислив несколько требований, которые помогут нам спроектировать архитектуру нейронной сети, подходящую для компьютерного зрения: 1. На самых ранних слоях наша сеть должна одинаково реагировать на один и тот же патч независимо от того, где он расположен на изображении. Этот принцип называется *инвариантностью к сдвигу* (или *эквивариантностью к сдвигу*). 2. Самые ранние слои сети должны фокусироваться на локальных областях, не обращая внимания на содержимое удалённых частей изображения. Это принцип *локальности*. В конечном итоге эти локальные представления могут быть агрегированы для формирования предсказаний на уровне всего изображения. 3. По мере продвижения более глубоким слоям следует уметь захватывать признаки изображения с более широким охватом, подобно тому, как это происходит на высших уровнях зрительного восприятия в природе. Давайте посмотрим, как это переводится на язык математики. Ограничение многослойного перцептрона ------------------------------------- Для начала рассмотрим многослойный перцептрон (MLP), в котором в качестве входных данных используются двумерные изображения :math:`\mathbf{X}`, а их непосредственные скрытые представления :math:`\mathbf{H}` также представлены в виде матриц (в коде это двумерные тензоры), причём как :math:`\mathbf{X}`, так и :math:`\mathbf{H}` имеют одинаковую форму. Осмыслите это. Теперь мы представляем себе, что не только входные данные, но и скрытые представления обладают пространственной структурой. Пусть :math:`[\mathbf{X}]_{i, j}` и :math:`[\mathbf{H}]_{i, j}` обозначают пиксель в позиции :math:`(i,j)` во входном изображении и скрытом представлении соответственно. Следовательно, чтобы каждый скрытый нейрон получал входные данные от каждого входного пикселя, мы должны перейти от использования матриц весов (как мы делали ранее в многослойных перцептронах) к представлению наших параметров в виде весовых тензоров четвёртого порядка :math:`\mathsf{W}`. Предположим, что :math:`\mathbf{U}` содержит смещения; тогда полносвязный слой можно формально записать как .. math:: \begin{aligned} \left[\mathbf{H}\right]_{i, j} &= [\mathbf{U}]_{i, j} + \sum_k \sum_l[\mathsf{W}]_{i, j, k, l} [\mathbf{X}]_{k, l}\\ &= [\mathbf{U}]_{i, j} + \sum_a \sum_b [\mathsf{V}]_{i, j, a, b} [\mathbf{X}]_{i+a, j+b}.\end{aligned} Переход от :math:`\mathsf{W}` к :math:`\mathsf{V}` пока носит исключительно косметический характер, поскольку существует взаимно однозначное соответствие между коэффициентами обоих тензоров четвертого порядка. Мы просто переиндексируем индексы :math:`(k, l)` так, чтобы выполнялись условия :math:`k = i+a` и :math:`l = j+b`. Иными словами, мы полагаем :math:`[\mathsf{V}]_{i, j, a, b} = [\mathsf{W}]_{i, j, i+a, j+b}`. Индексы :math:`a` и :math:`b` пробегают как положительные, так и отрицательные смещения, охватывая всё изображение. Для любой заданной позиции (:math:`i`, :math:`j`) в скрытом представлении :math:`[\mathbf{H}]_{i, j}` мы вычисляем его значение, суммируя значения пикселей в области :math:`x`, центрированной вокруг :math:`(i, j)` и взвешенной с помощью :math:`[\mathsf{V}]_{i, j, a, b}`. Прежде чем продолжить, рассмотрим общее количество параметров, необходимое для *одного* слоя при такой параметризации: изображение размером :math:`1000 \times 1000` (1 мегапиксель) отображается в скрытое представление размера :math:`1000 \times 1000`. Для этого требуется :math:`10^{12}` параметров, что далеко выходит за рамки возможностей современных компьютеров. Инвариантность к трансляции ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Теперь воспользуемся первым принципом, установленным выше: инвариантностью к сдвигу :cite:`Zhang.ea.1988`. Это означает, что сдвиг входа :math:`\mathbf{X}` должен приводить лишь к сдвигу скрытого представления :math:`\mathbf{H}`. Это возможно только в том случае, если :math:`\mathsf{V}` и :math:`\mathbf{U}` фактически не зависят от :math:`(i, j)`. Таким образом, мы получаем :math:`[\mathsf{V}]_{i, j, a, b} = [\mathbf{V}]_{a, b}`, а :math:`\mathbf{U}` является константой, обозначим её как :math:`u`. В результате мы можем упростить определение для :math:`\mathbf{H}`: .. math:: [\mathbf{H}]_{i, j} = u + \sum_a\sum_b [\mathbf{V}]_{a, b} [\mathbf{X}]_{i+a, j+b}. Это и есть *свёртка*! Мы фактически взвешиваем значения пикселей :math:`(i+a, j+b)` в окрестности позиции :math:`(i, j)` с помощью коэффициентов :math:`[\mathbf{V}]_{a, b}`, чтобы получить значение :math:`[\mathbf{H}]_{i, j}`. Обратите внимание, что :math:`[\mathbf{V}]_{a, b}` требует значительно меньшего числа коэффициентов, чем :math:`[\mathsf{V}]_{i, j, a, b}`, поскольку оно больше не зависит от положения в пределах изображения. Следовательно, количество требуемых параметров теперь составляет не :math:`10^{12}`, а гораздо более разумное :math:`4 \times 10^6`: зависимость от :math:`a, b \in (-1000, 1000)` сохраняется. Короче говоря, мы достигли значительного прогресса. Временные нейронные сети с задержкой (TDNN) являются одними из первых примеров, использующих эту идею :cite:`Waibel.Hanazawa.Hinton.ea.1989`. Локальность ~~~~~~~~~~~ Теперь обратимся ко второму принципу: локальности. Как было показано выше, мы полагаем, что для получения релевантной информации, необходимой для оценки того, что происходит в точке :math:`[\mathbf{H}]_{i, j}`, нам не нужно обращаться к данным, находящимся слишком далеко от точки :math:`(i, j)`. Это означает, что вне некоторого диапазона :math:`|a|> \Delta` или :math:`|b| > \Delta` мы должны установить значение :math:`[\mathbf{V}]_{a, b} = 0`. Эквивалентно, мы можем переписать выражение :math:`[\mathbf{H}]_{i, j}` следующим образом: .. math:: [\mathbf{H}]_{i, j} = u + \sum_{a = -\Delta}^{\Delta} \sum_{b = -\Delta}^{\Delta} [\mathbf{V}]_{a, b} [\mathbf{X}]_{i+a, j+b}. :label: eq_conv-layer Это уменьшает количество параметров с :math:`4 \times 10^6` до :math:`4 \Delta^2`, где :math:`\Delta` обычно меньше, чем :math:`10`. Таким образом, мы ещё на четыре порядка сократили число параметров. Обратите внимание, что :eq:`eq_conv-layer`, если говорить кратко, является *свёрточным слоем*. *Свёрточные нейронные сети* (CNN) — это особый класс нейронных сетей, содержащих свёрточные слои. В научном сообществе по глубокому обучению :math:`\mathbf{V}` называют *свёрточным ядром*, *фильтром* или просто *весами* слоя, которые являются обучаемыми параметрами. Ранее для представления всего одного слоя в сети обработки изображений могло потребоваться миллиарды параметров, тогда как сейчас обычно достаточно всего нескольких сотен, без изменения размерности ни входных данных, ни скрытых представлений. Ценой такого радикального сокращения числа параметров является то, что наши признаки становятся инвариантными к сдвигу, а слой может учитывать только локальную информацию при определении значения каждой скрытой активации. Любое обучение основано на наложении индуктивного смещения. Когда это смещение соответствует реальности, мы получаем модели, эффективно использующие примеры и хорошо обобщающиеся на невиданные данные. Но, разумеется, если эти смещения не соответствуют действительности, например, если изображения не являются инвариантными к сдвигу, наши модели могут испытывать трудности даже с подгонкой под обучающие данные. Это радикальное сокращение числа параметров подводит нас к нашему последнему требованию, а именно: более глубокие слои должны отражать всё более крупные и сложные аспекты изображения. Этого можно достичь, многократно чередуя нелинейные преобразования и свёрточные слои. Свёртки ------- Давайте кратко рассмотрим, почему :eq:`eq_conv-layer` называется свёрткой. В математике *свёртка* двух функций :cite:`Rudin.1973`, например :math:`f, g: \mathbb{R}^d \to \mathbb{R}`, определяется как .. math:: (f * g)(\mathbf{x}) = \int f(\mathbf{z}) g(\mathbf{x}-\mathbf{z}) d\mathbf{z}. То есть мы измеряем перекрытие между :math:`f` и :math:`g`, когда одна функция «переворачивается» и сдвигается на :math:`\mathbf{x}`. Всякий раз, когда мы имеем дело с дискретными объектами, интеграл превращается в сумму. Например, для векторов из множества бесконечномерных квадратично суммируемых векторов, где индекс пробегает значения :math:`\mathbb{Z}`, мы получаем следующее определение: .. math:: (f * g)(i) = \sum_a f(a) g(i-a). Для двумерных тензоров соответствующая сумма имеет индексы :math:`(a, b)` для :math:`f` и :math:`(i-a, j-b)` для :math:`g` соответственно: .. math:: (f * g)(i, j) = \sum_a\sum_b f(a, b) g(i-a, j-b). :label: eq_2d-conv-discrete Это выглядит аналогично :eq:`eq_conv-layer`, с одним существенным отличием. Вместо :math:`(i+a, j+b)` мы используем разность. Однако отметим, что это различие носит скорее формальный характер, поскольку мы всегда можем согласовать обозначения между :eq:`eq_conv-layer` и :eq:`eq_2d-conv-discrete`. Наше первоначальное определение в :eq:`eq_conv-layer` более точно описывает *перекрёстную корреляцию*. Мы вернёмся к этому в следующем разделе. .. _subsec_why-conv-channels: Каналы ------ Возвращаясь к нашему детектору Вальдо, посмотрим, как это выглядит. Свёрточный слой выделяет окна заданного размера и взвешивает интенсивности в соответствии с фильтром :math:`\mathsf{V}`, как показано в :numref:`fig_waldo_mask`. Мы можем стремиться к тому, чтобы модель обучалась так: там, где «вальдоность» максимальна, в представлениях скрытого слоя должен наблюдаться пик. .. _fig_waldo_mask: .. figure:: ../img/waldo-mask.jpg :width: 400px Найти Вальдо (изображение предоставлено Уильямом Мерфи (Infomatique)). У этого подхода есть одна проблема. До сих пор мы беззаботно игнорировали тот факт, что изображения состоят из трёх каналов: красного, зеленого и синего. В совокупности изображения представляют собой не двумерные объекты, а тензоры третьего порядка, характеризующиеся высотой, шириной и числом каналов, например, с формой :math:`1024 \times 1024 \times 3` пикселей. Если первые две оси отражают пространственные соотношения, то третью можно рассматривать как присвоение многомерного представления каждой позиции пикселя. Таким образом, мы индексируем :math:`\mathsf{X}` как :math:`[\mathsf{X}]_{i, j, k}`. Свёрточный фильтр должен соответствующим образом адаптироваться. Вместо :math:`[\mathbf{V}]_{a,b}` теперь у нас есть :math:`[\mathsf{V}]_{a,b,c}`. Более того, поскольку наши входные данные представляют собой тензор третьего порядка, оказывается целесообразным аналогичным образом представить наши скрытые представления в виде тензоров третьего порядка :math:`\mathsf{H}`. Иными словами, вместо того чтобы иметь одно скрытое представление для каждой пространственной позиции, мы хотим иметь целый вектор скрытых представлений для каждой такой позиции. Скрытые представления можно представить как набор двумерных сеток, уложенных друг на друга. Как и во входных данных, их иногда называют *каналами*. Их также иногда называют *картами признаков*, поскольку каждая из них предоставляет пространственно распределенный набор обученных признаков для последующего слоя. Интуитивно можно предположить, что на нижних слоях, ближайших к входам, некоторые каналы могут специализироваться на распознавании краев, тогда как другие — на распознавании текстур. Чтобы поддерживать несколько каналов как во входных данных (:math:`\mathsf{X}`), так и в скрытых представлениях (:math:`\mathsf{H}`), мы можем добавить четвёртое измерение к (:math:`\mathsf{V}`): (:math:`[\mathsf{V}]_{a, b, c, d}`). Объединяя всё вместе, получаем: .. math:: [\mathsf{H}]_{i,j,d} = \sum_{a = -\Delta}^{\Delta} \sum_{b = -\Delta}^{\Delta} \sum_c [\mathsf{V}]_{a, b, c, d} [\mathsf{X}]_{i+a, j+b, c}, :label: eq_conv-layer-channels где :math:`d` соответствует индексу выходных каналов в скрытых представлениях :math:`\mathsf{H}`. Следующий свёрточный слой принимает на вход тензор третьего порядка, :math:`\mathsf{H}`. В качестве определения свёрточного слоя для нескольких каналов мы выбираем :eq:`eq_conv-layer-channels`, поскольку оно является наиболее общим, где :math:`\mathsf{V}` — это ядро или фильтр слоя. Остаётся рассмотреть множество операций. Например, нам нужно определить, как объединить все скрытые представления в один выходной сигнал, например, чтобы установить, находится ли Вальдо *где-либо* на изображении. Нам также необходимо решить, как эффективно вычислять результаты, как комбинировать несколько слоёв, какие функции активации использовать и как принимать обоснованные проектные решения, чтобы сети эффективно работали на практике. Этим вопросам мы посвятим оставшуюся часть главы. Итоги и обсуждение ------------------ В этом разделе мы вывели структуру свёрточных нейронных сетей, исходя из первых принципов. Хотя неясно, был ли этот путь использован при создании CNN, приятно осознавать, что они являются *правильным* выбором, если применять разумные принципы к тому, как должны работать алгоритмы обработки изображений и компьютерного зрения, по крайней мере на нижних уровнях. В частности, инвариантность изображений к сдвигу означает, что все фрагменты изображения будут обрабатываться одинаково. Локальность подразумевает, что для вычисления соответствующих скрытых представлений будет использоваться лишь небольшое соседство пикселей. Одни из самых ранних упоминаний о CNN встречаются в виде нейрокогнитрона :cite:`Fukushima.1982`. Второй принцип, с которым мы столкнулись в ходе рассуждений, заключается в том, как уменьшить количество параметров в классе функций, не ограничивая при этом его выразительную способность, по крайней мере, при выполнении определённых предположений о модели. Мы наблюдали значительное снижение сложности в результате этого ограничения, что позволило превратить вычислительно и статистически неразрешимые задачи в управляемые модели. Добавление каналов позволило нам восстановить часть сложности, утраченной из-за ограничений, наложенных на свёрточное ядро локальностью и инвариантностью к сдвигу. Обратите внимание, что вполне естественно добавлять каналы, помимо красного, зелёного и синего. Многие спутниковые снимки, особенно в сельском хозяйстве и метеорологии, имеют от десятков до сотен каналов, образуя гиперспектральные изображения. Они содержат данные для множества различных длин волн. В дальнейшем мы рассмотрим, как эффективно использовать свёртки для управления размерностью обрабатываемых ими изображений, как переходить от представлений, основанных на расположении, к канальным, и как эффективно справляться с большим числом категорий. Упражнения ---------- 1. Предположим, что размер свёрточного ядра равен :math:`\Delta = 0`. Покажите, что в этом случае свёрточное ядро реализует многослойный перцептрон (MLP) независимо для каждого набора каналов. Это приводит к архитектуре Network in Network :cite:`Lin.Chen.Yan.2013`. 2. Аудиоданные часто представляются в виде одномерной последовательности. 1. Когда может потребоваться наложить ограничения локальности и трансляционной инвариантности для аудиоданных? 2. Выведите операции свёртки для аудио. 3. Можно ли применять к аудио те же инструменты, что и в компьютерном зрении? Подсказка: используйте спектрограмму. 3. Почему инвариантность к трансляции может оказаться не такой уж хорошей идеей? Приведите пример. 4. Как вы думаете, могут ли свёрточные слои также применяться к текстовым данным? С какими проблемами вы можете столкнуться при работе с языком? 5. Что происходит со свёртками, когда объект находится на границе изображения? 6. Докажите, что свёртка симметрична, т. е. :math:`f * g = g * f`. `Обсуждения `__