Введение в свёрточные нейронные сети (Convolutional Neural Networks)

  • Tutorial
Полный курс на русском языке можно найти по этой ссылке.
Оригинальный курс на английском доступен по этой ссылке.


Выход новых лекций запланирован каждые 2-3 дня.

Интервью с Себастьяном


— Итак, мы снова с Себастьяном в третьей части этого курса. Себастьян, я знаю, что вы проводили много разработок с использованием свёрточных нейронных сетей. Можете нам рассказать чуточку больше об этих сетях и что они собой представляют? Я уверена, что студенты нашего курса будут слушать с не меньшим интересом, потому что в этой части им предстоит разрабатывать свёрточную нейронную сеть самим.
— Отлично! Итак, свёрточные нейронные сети это великолепный способ структурирования в сети, построения так называемой инвариантности (выделения неизменяемых признаков). Например, возьмём идею распознавания образов на сцене или фотографии, вы хотите понять изображён ли Себастьян на ней или нет. Не важно в какой части фотографии я располагаюсь, где располагается моя голова — по центру фотографии или в углу. Распознавание моей головы, моего лица должно происходить вне зависимости от того, где они расположены на изображении. Это и есть инвариантность, вариативность местоположения, которая реализуется свёрточными нейронными сетями.
— Очень интересно! Можете назвать нам основные задачи в которых применяются свёрточные нейронные сети?
— Свёрточные нейронные сети достаточно плотно используются при работе с аудио и видео, включая медицинские изображения. Так же они используются в языковых технологиях, где специалисты используют глубокое обучение для понимания и воспроизведения языковых конструкций. На самом деле применений у этой технологии очень много, я бы даже сказал, что они безграничны! Её, технологию, можно использовать в финансах и любых других областях.
— Я использовала свёрточные нейронные сети для анализа снимков со спутников.
— Здорово! Стандартная задача!
— Как вы думаете, можем ли мы считать свёрточные нейронные сети чем-то последним и самым продвинутым инструментом в развитии глубокого обучения?
— Ха! Я уже научился никогда не говорить «никогда». Всегда будет находиться нечто новое и потрясающее!
— Значит нам ещё предстоит поработать? :)
— Работы будет достаточно!
— Превосходно! В этом курсе мы как раз обучаем будущих пионеров машинного обучения. Есть ли у вас пожелания нашим студентам, перед тем как они начнут строить свою первую свёрточную нейронную сеть?
— Вот вам интересный факт. Свёрточные нейронные сети были изобретены в 1989 году, а это очень давно! Большинство из вас даже не родились ещё в то время, а это означает, что не гениальность алгоритма имеет огромное значение, а данные, которыми оперирует этот алгоритм. Мы живём в мире, где предостаточно данных для анализа и поиска закономерностей. У нас есть возможность эмулировать функции человеческого разума используя это огромное количество данных. Когда вы будете работать над свёрточными нейронными сетями, попробуйте сфокусироваться на поиске правильных данных и их применении — посмотрите, что из этого получится и, порой, это может оказаться настоящей магией, как было в нашем случае, когда мы решали задачу определения рака кожи.
— Великолепно! Ну, что, давайте наконец-то займёмся магией!

Введение


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



Результаты, которых мы добились в процессе работы над нейронной сетью, были впечатляющими — 88% точность классификации. И это в несколько строк кода (не учитывая код построения графиков и изображений)!

model = tf.keras.Sequential([
   tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
   tf.keras.layers.Dense(128, activation=tf.nn.relu),
   tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

model.compile(optimizer='adam',
                      loss='sparse_categorical_crossentropy',
                      metrics=['accuracy'])

NUM_EXAMPLES = 60000
train_dataset = train_dataset.repeat().shuffle(NUM_EXAMPLES).batch(32)
test_dataset = test_dataset.batch(32)

model.fit(train_dataset, epochs=5, steps_per_epoch=math.ceil(num_train_examples/32))

test_loss, test_accuracy = model.evaluate(test_dataset, steps=math.ceil(num_test_examples/32))
print('Точность: ', test_accuracy)

Точность: 0.8782

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

На этом занятии мы узнаем, насколько легко разработать СНС-классификатор с нуля используя TensorFlow и Keras. Мы будем использовать тот же набор данных Fashion MNIST, который использовали на предыдущем занятии. В конце этого занятия мы сравним точность классификации элементов одежды предыдущей нейронной сети со свёрточной нейронной сетью из этого занятия.

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

Две основные концепции в свёрточных нейронных сетях:

  • свёртка
  • операция подвыборки (pooling, max pooling)


Давайте рассмотрим их подробнее.

Свёртка


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

Возьмём изображение в оттенках серого и, для примера, представим, что его размеры 6 px в высоту и 6 px в ширину.



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

На изображении ниже мы видим представление изображения 6px x 6px и соответствующие значения пикселей:



Как вы уже знаете, перед работой с изображениями значения пикселей необходимо нормализовать — привести значения к интервалу от 0 до 1. Однако в данном примере, для удобства пояснений, сохраним значения пикселей изображения и не будет их нормализовать.

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



Затем мы можем просканировать наше изображение с использованием ядра. Размеры нашего изображения 6х6px, а ядра — 3x3px. Свёрточный слой применяется к ядру и каждому участку входного изображения.

Давайте представим себе, что мы хотим выполнить свёртку над пикселем со значением 25 (3 строка, 3 столбец) и первым делом, что необходимо сделать — центрировать ядро над этим пикселем:



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

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







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



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



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

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

Теперь давайте рассмотрим вторую концепцию свёрточных нейронных сетей — операцию подвыборки (pooling, max-pooling).

Операция подвыборки (pooling, max-pooling)


Сейчас мы рассмотрим вторую фундаментальную концепцию лежащую в основе свёрточных нейронных сетей — операцию подвыборки (pooling, max-pooling). Простыми словами, операция подвыборки это процесс сжатия (уменьшения размеров) изображения путём сложения значений блоков пикселей. Давайте рассмотрим как это работает на конкретном примере.



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

После того как мы определились с размером сетки и размером шага нам необходимо найти максимальное значение пикселя попадающее в выделенную сетку. В пример выше в сетку попадают значения 1, 0, 4, 8, 2, 5, 20, 13, 25. Максимальное значение — 25. Это значение «переносится» в новое изображение. Сетка сдвигается на 3 пикселя вправо и процесс выборки максимального значения и его переноса на новое изображение повторяется.



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

Давайте посмотрим как это будет работать в Python!

Резюме


Мы познакомились с такими понятиями как свёртка и операция подвыборки (max-pooling).

Свёртка — процесс применения фильтра («ядра») к изображению. Операция подвыборки по максимальному значению — процесс уменьшения размеров изображения через объединение группы пикселей в единое максимальное значение из этой группы.

Как мы увидим в практической части, свёрточный слой может быть добавлен к нейронной сети с использованием Conv2D-слоя в Keras. Этот слой подобен Dense-слою, и содержит веса и смещения, которые подвергаются оптимизации (подбору). Conv2D-слой так же содержит фильтры («ядра»), значения которых тоже оптимизируются. Итак, в Conv2D-слое значения внутри матрицы фильтра и есть переменные, которые подвергаются оптимизации.

Некоторые термины с которыми мы успели столкнуться:

  • СНС — свёрточные нейронные сети. Нейронная сеть, которая содержит хотя бы один свёрточный слой. Типичная СНС содержит и другие слои, такие как слои выборки и полносвязные слои.
  • Свёртка — процесс применения фильтра («ядра») к изображению.
  • Фильтр (ядро) — матрица, по размерам меньше, чем входные данные, предназначенная для преобразования входных данных блоками.
  • Выравнивание — процесс добавления, чаще всего нулевых значений, по краям изображения.
  • Операция подвыборки — процесс уменьшения размера изображения через сэмплирование. Существует несколько типов слоёв подвыборки, например, слой усредненной подвыборки (выборка среднего значения), однако подвыборка по максимальному значению используется чаще всего.
  • Подвыборка по максимальному значению — процесс подвыборки, в ходе которого множество значений преобразовываются в единое значение — максимальное среди выборки.
  • Шаг — количество пикселей смещения фильтром (ядром) на изображении.
  • Сэмплирование (downsampling) — процесс уменьшения размера изображения.

CoLab: классификация элементов одежды Fashion MNIST с использованием свёрточной нейронной сети


Нас обвели вокруг пальца! Данную практическую часть есть смысл выполнять только после выполнения предыдущей части — весь код, кроме одного блока, остаётся прежним. Меняется структура нашей нейронной сети, а это — четыре дополнительные строки для свёрточных нейронных слоёв и слоёв подвыборки по максимальному значению (max-pooling).

model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, (3,3), padding='same', activation=tf.nn.relu,
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D((2, 2), strides=2),
    tf.keras.layers.Conv2D(64, (3,3), padding='same', activation=tf.nn.relu),
    tf.keras.layers.MaxPooling2D((2, 2), strides=2),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation=tf.nn.relu),
    tf.keras.layers.Dense(10,  activation=tf.nn.softmax)
])

Все детальные пояснения, как это работать, нам обещают дать в следующей части — 4 части.

Ах, да. Точность модели на этапе обучения стала равна 97% (модель «переобучилась» при epochs=10), а при прогонке по набору данных для тестов показала точно 91%. Заметный прирост точности относительно предыдущей архитектуры, где у нас были использованы только полносвязаные слои — 88%.

Итоги


В этой части занятия мы изучили новый тип нейронных сетей — свёрточные нейронные сети. Познакомились с такими терминами как «свёртка» и «операция подвыборки по максимальному значению» (max-pooling), разработали и обучили свёрточную нейронную сеть с нуля. В результе мы увидели, что наша свёрточная нейронная сеть выдаёт точность больше, чем нейронная сеть, которую мы разрабатывали на прошлом занятии.

P.S. Примечание от автора перевод.

Курс называется «Введение в глубокое обучение с использованием TensorFlow», поэтому сетовать на то, что нет детализированных пояснений по принципу работы свёрточных нейронных сетей (слоёв) мы не будем — следующие две статьи будут как раз о принципе работы свёрточной нейронной сети и их внутренней структуре (статьи не касаются курса, а были рекомендованы участниками StackOverflow для лучшего понимания происходящего).

… и стандартные call-to-action — подписывайся, ставь плюс и делай share :)
YouTube
Telegram
ВКонтакте
Support the author
Share post

Comments 0

Only users with full accounts can post comments. Log in, please.