[Перевод] Анализ сверточных слоев нейронных сетей глубокого обучения

искусственный интеллект глубокое обучение Программа перевода самородков Python Нейронные сети
[Перевод] Анализ сверточных слоев нейронных сетей глубокого обучения

фотоmendhakСфотографировано, все права защищены.

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

Свертка — это просто активация ввода через фильтр. Карта активации, полученная путем многократного применения одного и того же фильтра к входным данным, называется картой признаков/картой признаков и представляет расположение и интенсивность признаков, обнаруженных во входных данных (например, в изображении).

Сверточные нейронные сети в условиях ограничений конкретных задач прогнозного моделирования (таких как классификация изображений) могут инновационно и автоматически изучать большое количество фильтров параллельно в обучающем наборе данных. В результате в любом месте входного изображения можно обнаружить очень специфические особенности.

В этом уроке вы узнаете, как работает свертка в сверточных нейронных сетях.

После прохождения этого урока вы будете знать:

  • Сверточные нейронные сети используют фильтры для получения карты объектов из входных данных, которая обобщает наличие признаков, обнаруженных во входных данных.
  • Фильтры можно спроектировать вручную, например линейные детекторы, но инновация сверточных нейронных сетей заключается в том, что фильтры изучаются во время обучения в контексте конкретной задачи прогнозирования.
  • Как вычислить карты объектов для одномерных и двумерных сверточных слоев в сверточной нейронной сети.

Давайте начнем.

Обзор учебника

Этот учебник разделен на четыре части, а именно:

  1. Свертка в сверточных нейронных сетях
  2. Свертка в компьютерном зрении
  3. Способность изученного фильтра
  4. Пример сверточного слоя

Свертка в сверточных нейронных сетях

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

Ядром сверточной нейронной сети является сверточный слой, который также является источником названия сверточной нейронной сети. Операции, выполняемые этим слоем, называются "свертка".

В контексте сверточных нейронных сетей свертка — это линейная операция, которая включает в себя умножение набора весов на вход, как и в традиционной нейронной сети. Поскольку метод предназначен для двумерных входных данных, это умножение выполняется между массивом входных данных и двумерным массивом весов, называемым фильтром или ядром.

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

Мы намеренно используем фильтр меньшего размера, чем вход, так как он позволяет одному и тому же фильтру (набору весов) многократно умножать входной массив в разных точках входа. В частности, фильтры систематически применяются к каждой перекрывающейся части или блоку входных данных размером с фильтр слева направо и сверху вниз.

Систематическое применение одного и того же фильтра к изображению — мощная идея. Если фильтр предназначен для обнаружения объекта определенного типа на входе, то систематическое применение фильтра ко всему входному изображению может дать возможность найти этот объект в любом месте изображения. Эту способность часто называют трансляционной инвариантностью, т. е. сосредоточением внимания на том, существует ли функция, а не на том, где она существует.

Локальная трансляционная инвариантность может быть очень полезным свойством, если нас больше интересует, присутствует ли функция, а не точное место, где она присутствует. Например, при определении того, содержит ли изображение лицо, нам не нужно знать точное положение глаз на уровне пикселей, нам нужно только знать, что один глаз находится слева, а другой — справа от лица. .

- стр. 342,глубокое обучение, 2016.

Умножьте фильтр на входной массив один раз, чтобы получить одно значение. Поскольку фильтр применяется к входному массиву несколько раз, результатом является двумерный массив выходных значений, представляющий отфильтрованный ввод, и этот результат называется «карта объектов".

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

对二维输入创建特征映射的滤波器示例

Пример фильтра для создания карты объектов на 2D-вводе

Если вы пришли из области цифровой обработки сигналов или связанной с ней математики, вы, вероятно, понимаете операцию свертки матриц как нечто иное. В частности, переверните фильтр (ядро) перед применением ввода. Теоретически свертка в сверточных нейронных сетях на самом деле «Корреляция". Однако в глубоком обучении это называется"свертка"действуй.

Взаимная корреляция, реализуемая многими библиотеками машинного обучения, называется сверткой.

- стр. 333,глубокое обучение, 2016.

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

Свертка в компьютерном зрении

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

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

Например, вот созданный вручную элементный фильтр 3×3 для обнаружения вертикальных линий:

0.0, 1.0, 0.0

0.0, 1.0, 0.0

0.0, 1.0, 0.0

Применение этого фильтра к изображению создаст карту объектов, содержащую только вертикальные линии. Это детектор вертикальной линии.

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

Мы также можем создать детектор горизонтальных линий и применить его к изображению, например:

0.0, 0.0, 0.0

1.0, 1.0, 1.0

0.0, 0.0, 0.0

Объединение результатов двух фильтров, например объединение двух карт объектов, выделит все линии на изображении.

Набор из десятков или даже сотен других небольших фильтров может быть разработан для обнаружения других особенностей изображения.

Новшество использования операций свертки в нейронных сетях заключается в том, что значения фильтров являются весами, которые необходимо выучить при обучении сети.

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

В этом случае вы увидите, что это очень мощная идея.

Способность изученного фильтра

Изучение одного фильтра для задач машинного обучения — мощная техника.

Однако на практике сверточные нейронные сети достигают гораздо большего.

несколько фильтров

Сверточные нейронные сети не просто изучают один фильтр. Фактически, они изучают несколько функций параллельно для заданного ввода.

Например, сверточный слой обычно изучает от 32 до 512 фильтров параллельно для данного входа.

Это дает модели 32 или даже 512 различных способов извлечения признаков из входных данных, или «научиться видеть«Много разных способов и после тренировки»Смотреть"Много разных способов ввода данных.

Это разнообразие позволяет настраивать, например, не только линии, но и определенные строки в конкретных тренировочных данных.

несколько каналов

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

С точки зрения данных это означает, что одно входное изображение на самом деле представляет собой три изображения в модели.

Фильтр всегда должен иметь то же количество каналов, что и вход, что часто называют «глубина". Если входное изображение имеет 3 канала (глубина 3), фильтр, примененный к этому изображению, также должен иметь 3 канала (глубина 3). В этом случае фильтр 3×3 фактически представляет собой строку, столбец. Суммарная глубина 3x3x3 или [3, 3, 3].Операция скалярного произведения используется для применения фильтра к входным данным для получения одного значения, независимо от глубины ввода и фильтра.

Это означает, что если сверточный слой имеет 32 фильтра, эти 32 фильтра являются не только 2D, но и 3D для ввода 2D-изображения с определенными весами фильтров для каждого из трех каналов. Однако каждый фильтр создает карту объектов, а это означает, что для 32 созданных карт объектов выходная глубина сверточного слоя, применяющего 32 фильтра, равна 32.

несколько слоев

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

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

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

Фильтр, работающий с выходными данными первого линейного слоя, может извлекать функции, которые синтезируют низкоуровневые функции, такие как функции нескольких линий, которые могут представлять формы.

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

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

Пример сверточного слоя

Библиотека глубокого обучения Keras предоставляет ряд сверточных слоев.

Мы можем лучше понять операцию свертки, рассмотрев несколько примеров искусственных данных и созданных вручную фильтров.

В этом разделе мы рассмотрим примеры как одномерных сверточных слоев, так и двумерных сверточных слоев, которые воплощают операции свертки и демонстрируют демонстрацию использования слоев Keras.

Пример одномерного сверточного слоя

Мы можем определить одномерный ввод с восемью элементами, два приподнятых элемента в середине имеют значение 1,0, а остальные элементы имеют значение 0,0.

[0, 0, 0, 1, 1, 0, 0, 0]

Для одномерного сверточного слоя входные данные для Keras должны быть трехмерными.

Первое измерение относится к каждой входной выборке, в этом случае у нас есть только одна выборка. Второе измерение относится к длине каждого образца, которая в данном случае равна 8. Третье измерение относится к количеству каналов в каждом образце, в данном случае у нас есть только один канал.

Поэтому форма входного массива [1, 8, 1].

# define input data
data  =  asarray([0,  0,  0,  1,  1,  0,  0,  0])
data  =  data.reshape(1,  8,  1)

Мы определим модель с входными выборками формы [8, 1].

Модель будет иметь фильтр формы 3 или шириной в три элемента. Керас относится к форме фильтра какkernel_size.

# create model
model  =  Sequential()
model.add(Conv1D(1,  3,  input_shape=(8,  1)))

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

Определим трехэлементный фильтр следующим образом:

[0, 1, 0]

Сверточный слой также имеет входное значение смещения, которое также требует, чтобы мы установили вес 0.

Следовательно, мы можем заставить веса наших одномерных сверточных слоев использовать созданные вручную фильтры, как показано ниже:

# define a vertical line detector
weights = [asarray([[[0]],[[1]],[[0]]]), asarray([0.0])]
# store the weights in the model
model.set_weights(weights)

Веса должны быть установлены в трехмерной структуре строк, столбцов и каналов.Фильтры имеют одну строку, три столбца и один канал.

Мы можем получить веса и убедиться, что они установлены правильно.

# confirm they were stored
print(model.get_weights())

Наконец, мы можем применить один фильтр к входным данным.

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

# apply filter to input data
yhat  =  model.predict(data)
print(yhat)

Собрав все это вместе, полный пример приведен ниже.

# example of calculation 1d convolutions
from numpy import asarray
from keras.models import Sequential
from keras.layers import Conv1D
# define input data
data = asarray([0, 0, 0, 1, 1, 0, 0, 0])
data = data.reshape(1, 8, 1)
# create model
model = Sequential()
model.add(Conv1D(1, 3, input_shape=(8, 1)))
# define a vertical line detector
weights = [asarray([[[0]],[[1]],[[0]]]), asarray([0.0])]
# store the weights in the model
model.set_weights(weights)
# confirm they were stored
print(model.get_weights())
# apply filter to input data
yhat = model.predict(data)
print(yhat)

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

Затем к входным шаблонам применяются фильтры, вычисляются и отображаются карты объектов. Из значения карты признаков видно, что выпуклость обнаружена правильно.

[array([[[0.]],
       [[1.]],
       [[0.]]], dtype=float32), array([0.], dtype=float32)]

[[[0.]
  [0.]
  [1.]
  [1.]
  [0.]
  [0.]]]

Давайте поближе посмотрим, что происходит.

Напомним, что вход представляет собой восьмиэлементный вектор со значениями: [0, 0, 0, 1, 1, 0, 0, 0].

Во-первых, трехэлементный фильтр [0, 1, 0] применяется к первым трем входам [0, 0, 0] входа путем вычисления скалярного произведения (оператор.), в результате чего получается одно выходное значение 0 на карте объектов.

Напомним, что скалярное произведение — это сумма произведений соответствующих элементов, в данном случае это (0 x 0) + (1 x 0) + (0 x 0) = 0. В NumPy это можно реализовать вручную как:

from numpy import asarray
print(asarray([0, 1, 0]).dot(asarray([0, 0, 0])))

В нашем ручном примере это выглядит следующим образом:

[0, 1, 0] . [0, 0, 0] = 0

Затем фильтр перемещается по одному элементу входной последовательности, и процесс повторяется. В частности, применение одного и того же фильтра к входной последовательности с индексами 1, 2 и 3 дает результат 0 на карте объектов.

[0, 1, 0] . [0, 0, 1] = 0

Мы систематичны, поэтому снова фильтр перемещается по другому элементу ввода и применяется к входу с индексами 2, 3 и 4. На этот раз выходное значение на карте объектов равно 1. Мы обнаруживаем эту функцию и активируем ее соответствующим образом.

[0, 1, 0] . [0, 1, 1] = 1

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

[0, 0, 1, 1, 0, 0]

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

Как вы можете себе представить, с разными входными данными мы можем обнаружить признаки с разной силой, с разными весами в фильтре, затем мы обнаружим разные признаки во входной последовательности.

Пример 2D-сверточного слоя

Мы можем расширить пример обнаружения выпуклости из предыдущего раздела до детектора вертикальных линий для 2D-изображений.

Точно так же мы можем ограничить ввод, здесь квадратное входное изображение 8x8 пикселей с одним каналом (например, в оттенках серого) с вертикальной линией посередине.

[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]

Входные данные для Conv2D (двумерный сверточный слой) должны быть четырехмерными.

Первое измерение определяет выборку, в данном случае имеется только одна выборка. Второе измерение определяет количество строк, в данном случае 8. Третье измерение определяет количество столбцов, в данном случае снова 8. Наконец, определите количество каналов, в данном случае 1.

Следовательно, вход должен иметь четырехмерную форму [выборки, столбцы, строки, каналы], в данном случае [1, 8, 8, 1].

# define input data
data = [[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0]]
data = asarray(data)
data = data.reshape(1, 8, 8, 1)

Мы определим Conv2D с одним фильтром, как мы сделали с примером Conv1D в предыдущем разделе.

Фильтр будет двумерным, квадрат формы 3х3. Слой будет ожидать, что входные образцы будут иметь форму [столбцы, строки, каналы], в данном случае [8, 8, 1].

# create model
model = Sequential()
model.add(Conv2D(1, (3,3), input_shape=(8, 8, 1)))

Мы определим фильтр детектора вертикальных линий для обнаружения одиночных вертикальных линий во входных данных.

Фильтр выглядит так:

0, 1, 0
0, 1, 0
0, 1, 0

Мы можем добиться следующего:

# define a vertical line detector
detector = [[[[0]],[[1]],[[0]]],
            [[[0]],[[1]],[[0]]],
            [[[0]],[[1]],[[0]]]]
weights = [asarray(detector), asarray([0.0])]
# store the weights in the model
model.set_weights(weights)
# confirm they were stored
print(model.get_weights())

Наконец, мы применяем фильтр к входному изображению, и мы получим карту признаков, указывающую на обнаружение вертикальных линий на входном изображении, как мы и хотели.

# apply filter to input data
yhat = model.predict(data)

Выходная форма карты объектов будет четырехмерной [пакет, строка, столбец, фильтр]. Мы выполним одну партию, и у нас есть один фильтр (один фильтр и один входной канал), поэтому выходная форма будет [1, ?, ?, 1]. Мы можем идеально распечатать содержимое одной карты объектов следующим образом:

for r in range(yhat.shape[1]):
	# print each column in the row
	print([yhat[0,r,c,0] for c in range(yhat.shape[2])])

Собрав все это вместе, полный пример приведен ниже.

# example of calculation 2d convolutions
from numpy import asarray
from keras.models import Sequential
from keras.layers import Conv2D
# define input data
data = [[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0]]
data = asarray(data)
data = data.reshape(1, 8, 8, 1)
# create model
model = Sequential()
model.add(Conv2D(1, (3,3), input_shape=(8, 8, 1)))
# define a vertical line detector
detector = [[[[0]],[[1]],[[0]]],
            [[[0]],[[1]],[[0]]],
            [[[0]],[[1]],[[0]]]]
weights = [asarray(detector), asarray([0.0])]
# store the weights in the model
model.set_weights(weights)
# confirm they were stored
print(model.get_weights())
# apply filter to input data
yhat = model.predict(data)
for r in range(yhat.shape[1]):
	# print each column in the row
	print([yhat[0,r,c,0] for c in range(yhat.shape[2])])

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

Затем распечатайте вычисленную карту объектов. Из шкалы чисел видно, что фильтр действительно обнаруживает вертикальную линию с одной сильной активацией в середине карты признаков.

[array([[[[0.]],
        [[1.]],
        [[0.]]],
       [[[0.]],
        [[1.]],
        [[0.]]],
       [[[0.]],
        [[1.]],
        [[0.]]]], dtype=float32), array([0.], dtype=float32)]

[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]

Рассмотрим подробнее, что считается.

Сначала примените фильтр к левому верхнему углу изображения или блоку изображения 3x3 элемента. По идее, патч изображения трехмерный, с одним каналом, а фильтры одинакового размера. В NumPy мы не можем использоватьdot()функция для ее реализации, мы должны использоватьtensordot()вместо этого используйте функцию, чтобы мы могли соответствующим образом суммировать все измерения, например:

from numpy import asarray
from numpy import tensordot
m1 = asarray([[0, 1, 0],
			  [0, 1, 0],
			  [0, 1, 0]])
m2 = asarray([[0, 0, 0],
			  [0, 0, 0],
			  [0, 0, 0]])
print(tensordot(m1, m2))

Этот расчет дает единственное выходное значение 0,0, что означает, что объекты не обнаружены. Это дает нам первый элемент в верхнем левом углу карты объектов.

Вручную выглядит так:

0, 1, 0     0, 0, 0
0, 1, 0  .  0, 0, 0 = 0
0, 1, 0     0, 0, 0

Переместите фильтр влево вдоль столбца и повторите процесс. Опять же, эта функция не была обнаружена.

0, 1, 0     0, 0, 1
0, 1, 0  .  0, 0, 1 = 0
0, 1, 0     0, 0, 1

Снова перемещаясь влево к следующему столбцу, функция обнаруживается впервые и сильно активируется.

0, 1, 0     0, 1, 1
0, 1, 0  .  0, 1, 1 = 3
0, 1, 0     0, 1, 1

Этот процесс повторяется до тех пор, пока край фильтра не окажется на краю или в последнем столбце входного изображения. Это дает последний элемент в первой полной строке карты объектов.

[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]

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

Как и в предыдущем разделе, мы видим, что карта признаков представляет собой матрицу 6×6, которая меньше входного изображения 8×8 из-за ограничений фильтра, примененного к входному изображению.

дальнейшее чтение

Если вы хотите углубиться, этот раздел содержит больше ресурсов по этой теме.

статья

Книга

API

Суммировать

В этом уроке вы узнали, как работают свертки в сверточных нейронных сетях.

В частности, вы узнали:

  • Сверточные нейронные сети используют фильтры для получения карты объектов из входных данных, которая обобщает наличие признаков, обнаруженных во входных данных.
  • Фильтры можно создавать вручную, например линейные детекторы, но инновация сверточных нейронных сетей заключается в том, что фильтры изучаются во время обучения в контексте конкретной задачи прогнозирования.
  • Как вычислить карты объектов для одномерных и двумерных сверточных слоев в сверточной нейронной сети.

В чем твоя проблема? Задавайте свои вопросы в комментариях ниже, и я постараюсь на них ответить.

Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.