- Название статьи: «Нелокальные нейронные сети»
- Адрес бумаги:АР Вест V.org/ABS/1711.07…
0 Обзор
Во-первых, модуль в этой статье называется нелокальным блоком, а затем эта идея основана на механизме само-внимания в НЛП. Поэтому, когда дело доходит до внимания к себе в резюме, первое, что приходит на ум, — это неместная газета. Мотивация, представленная в этой статье, выглядит следующим образом:
Как сверточные, так и рекурсивные операции работают с локальной окрестностью в пространстве или времени; долгосрочные корреляции могут быть зафиксированы только в том случае, если эти операции применяются многократно, распространяя сигнал пошагово через данные.
Другими словами, в сверточной сети, если вы хотите увеличить поле зрения, вы должны продолжать увеличиватьКоличество сверточных слоев и количество объединяющих слоев, другими словами, увеличение поля зрения увеличивает глубину сети. Это неизбежно приведет к увеличению стоимости расчета, количества параметров, а также необходимости учитывать проблему исчезновения градиента.
- В НЛП долговременная корреляция относится к корреляции между двумя словами, которые находятся далеко друг от друга в предложении, а в CV — к корреляции между двумя частями, которые находятся далеко друг от друга в изображении. Вообще CNN распознает объекты, и обращает внимание только на пиксели вокруг объекта, и не рассматривает очень дальние места, это тоже особенность CNN, локальное поле зрения. В некоторых случаях это естественное преимущество, а может, конечно, превратиться и в недостаток.
1 Основное содержание
На этот раз мы учимся сначала смотреть на код, а затем анализировать код с бумаги.
1.1 Преимущества нелокального
- Захват удаленных зависимостей с меньшим количеством параметров и слоев;
- Подключи и играй
1.2 репродукция питорча
class Self_Attn(nn.Module):
""" Self attention Layer"""
def __init__(self,in_dim,activation):
super(Self_Attn,self).__init__()
self.chanel_in = in_dim
self.activation = activation
self.query_conv = nn.Conv2d(in_channels = in_dim , out_channels = in_dim//8 , kernel_size= 1)
self.key_conv = nn.Conv2d(in_channels = in_dim , out_channels = in_dim//8 , kernel_size= 1)
self.value_conv = nn.Conv2d(in_channels = in_dim , out_channels = in_dim , kernel_size= 1)
self.gamma = nn.Parameter(torch.zeros(1))
self.softmax = nn.Softmax(dim=-1)
def forward(self,x):
"""
inputs :
x : input feature maps( B X C X W X H)
returns :
out : self attention value + input feature
attention: B X N X N (N is Width*Height)
"""
m_batchsize,C,width ,height = x.size()
proj_query = self.query_conv(x).view(m_batchsize,-1,width*height).permute(0,2,1) # B X CX(N)
proj_key = self.key_conv(x).view(m_batchsize,-1,width*height) # B X C x (*W*H)
energy = torch.bmm(proj_query,proj_key) # transpose check
attention = self.softmax(energy) # BX (N) X (N)
proj_value = self.value_conv(x).view(m_batchsize,-1,width*height) # B X C X N
out = torch.bmm(proj_value,attention.permute(0,2,1) )
out = out.view(m_batchsize,C,width,height)
out = self.gamma*out + x
return out,attention
1.3 Интерпретация кода
Карта входных объектов — это BatchxChannelxHeightxWidth, мы сначала помещаем эту карту входных объектов x в:
- Запросите сверточный слой, получите BatchxChannel//8xHeightxWidth
- ключевой слой свертки, получить BatchxChannel//8xHeightxWidth
- слой свертки значения, получить BatchxChannelxHeightxWidth
Нам нужно вычислить сходство между запросом и ключевым пикселем за пикселем, и тогда более важны пиксели с высоким сходством, а пиксели с низким сходством не так важны.Каждый пиксель представлен вектором длины канала//8. (Здесь может быть более абстрактно, ведь первоначальный вариант самовнимания находится в области НЛП, а нелокальный скопирован из НЛП, поэтому его нелегко понять напрямую.)
Сходство рассчитывается поумножение векторовЧтобы представить, то мы не должны вычислять сходство пикселей по одному с этим HeightxWidth таким количеством пикселей. Итак, мы конвертируем BatchxChannel//8xHeightxWidth в BatchxChannel//8xN, где N — это HeightxWidth, а N означаетколичество пикселей в изображении.
Затем мы используемtorch.bmm()
Чтобы выполнить умножение матриц: перемножьте две матрицы (N, Channel//8) и (Channel//8, N), чтобы получить матрицу (N, N).
Значение элементов i-й строки и j-го столбца в этой (N, N)-матрице представляет собой соотношение между пикселем в позиции i и пикселем в позиции j на рисунке! Затем мы выполняем матричное умножение между матрицей значений и этим (N, N), и результат, полученный таким образом, представляет собой карту объектов, которая учитывает глобальную информацию.
Во втором матричном умножении это умножение (Канал, N) и (N, N), и каждое значение в выходной карте объектов представляет собой средневзвешенное значение N значений, которое также показывает, что выход Каждое значение в объекте map учитывает пиксели всего изображения.
1.4 Интерпретация статьи
На приведенном выше рисунке представлена структурная схема нелокального языка в статье. Видно, что сначала пройти свертку 1х1, уменьшить количество каналов, а потом пройтиявляются запросом и ключом соответственно, а затем эти две свертки получают матрицу (N, N), которая затем объединяется с(значение) для выполнения матричного умножения.
Ну, я признаю, что есть небольшая разница с кодом, но общая идея та же.
2 Резюме
- После нелокальной карты признаков поле зрения расширяется до полного изображения без добавления большого количества параметров.
- Однако из-за умножения матрицы BMM график расчета градиента быстро расширяется, поэтому вычисления и память будут занимать много места. Поэтому я добавлю нелокальный слой в глубокий слой сети (когда размер карты признаков мал). но! ! ! В статье постарайтесь поместить его в передний слой, поэтому, когда вычислительная мощность позволит, выдвиньте его вперед.
- Этот метод действительно улучшился в некоторых задачах, я пробовал его сам, и это нормально.
- В будущем будет много алгоритмов, чтобы уменьшить потребление этих вычислений. Мы поговорим об этом позже. Если вам это нравится, пожалуйста, подпишитесь и поставьте лайк~