Смотреть материал на видео
Вы наверняка слышали, что НС способны решать задачи классификации графических образов (отличать кошку от собаки, самолет от автомобиля, мужчин от женщин и т.д.), делать стилизацию изображений, выполнять их раскраску, генерировать новые графические образы и делать много других интересных вещей с изображениями. И мы с вами научимся делать некоторые из этих эффектов. Так вот, когда речь заходит об обработке изображений, то используется особая архитектура НС – сверточные НС. По-английски звучит как:
Convolutional Neural Networks (CNN)
Изначально они были предложены Яном Лекуном и спроектированы для задач классификации графических образов. А началось все с того, что в 2012-м году команда Алекса Крижевски выиграла в ежегодном соревновании ImageNet по распознаванию графических образов. Их алгоритм показал точность в 83,6% правильной классификации – рекорд того времени. И этот рекорд был достигнут сверточной НС – AlexNet.
Общая идея архитектуры таких сетей была подсмотрена у биологической зрительной системы. Ученые выяснили, что дендриды каждого нейрона соединяются не со всеми рецепторами сетчатки глаза, а лишь с некоторой локальной областью. И уже дендриды всей группы зрительных нейронов покрывают сетчатку глаза целиком:
Математики обобщили эту структуру и предложили следующее решение. Входной сигнал изображения подается на вход нейрона только в пределах ограниченной области, как правило, квадратной, например, 3х3 пикселей. Затем, эта область смещается вправо на заданный шаг, допустим, 1 пиксель и входы подаются уже на второй нейрон. Так происходит сканирование всего изображения. Причем, весовые коэффициенты для всех нейронов этой группы – одинаковые.
После этого сканирование изображения повторяется, но с другим набором весовых коэффициентов. Получаем вторую группу нейронов. Затем, третью, четвертую и в общем случае имеем n различных групп. Так формируется первый скрытый слой нейронов сверточной НС.
Давайте теперь подробнее посмотрим, что получается на входах нейронов каждой отдельной группы. Так как весовые коэффициенты в пределах группы не меняются, то фактически, мы имеем окно (в нашем примере его размер 3х3 пиксела) с набором определенных чисел:
Эти числа умножаются на значения соответствующих пикселей изображения и суммируются:
И, кроме того, у каждой такой макси может быть еще один дополнительный параметр – bias (смещение), обозначим его через . Затем, окно смещается вправо (в нашем примере на один пиксел) и вычисления повтряются:
В общем виде для всего изображения сумму можно определить так:
То есть, перемещая это окно, весовые коэффициенты остаются неизменными и мы получаем общее число настраиваемых параметров для одной группы нейронов:
Соответственно, для n групп, получим:
Так вот, в цифоровой обработке сигналов эта сумма называется сверткой
, а окно с весовыми коэффициентами –
импульсным откликом фильтра
(или,
ядром фильтра
). В чем смысл такого фильтра? Давайте представим, что у нас имеется схематичное изображение дома и мы пропустим его через вот такие ядра:
На выходе получаем отчетливые вертикальные линии в первом случае и горизонтальные – во втором случае. Все остальные линии стали более бледными. То есть, фильтр позволяет выделять характерные участки на изображении в соответствии с конфигурацией весовых коэффициентов. Благодаря такому подходу, нейроны каждой группы активизируются, когда на участке изображения появляется фрагмент, подходящий под их ядра:
И на выходе формируется набор карт признаков, которые называются каналами
. Значимые величины в каждой карте показывают наличие признака в строго определенном месте изображения. Если таких признаков будет несколько (на разных участках изображения), то на выходе будут активироваться несколько нейронов, связанных с этими областями. Благодаря этому, следующие слои сверток могут обобщать найденные особенности до более сложных, например, эллипсов, прямоугольников, различных пересечений линий и т.п.
Разумеется, значения карт признаков – это выходы функций активации нейронов, то есть, здесь, все как обычно: сумма (свертка) проходит через функцию активации и формируются выходные значения:
Надеюсь, что концепция каналов СНС в целом понятна. Но мы рассмотрели простейший вариант, когда на вход подавалось одноканальное изображение, например, в градациях серого. Если обрабатывается полноцветное изображение, представленное, например, тремя цветовыми компонентами RGB, то каждая цветовая компонента сначала преобразовывается своим отдельным, независимым ядром, затем, вычисленные карты признаков, складываются, к ним добавляется смещение и формируется единая итоговая матрица признаков, которая проходит через функцию активации нейронов и получаются выходные значения на соответствующем канале.
Вот так выглядит обработка полноцветных изображений на первом скрытом слое СНС. Последующие слои работают по такому же принципу, только вместо цветовых каналов RGB, выполняется уже обработка каналов из карт признаков, сформированных на предыдущем слое.
И последний важный момент. Смотрите, после обработки исходного изображения каждый канал, фактически, формирует новое изображение немного меньшего размера:
Если изначально было изображение, например, 128×128 пикселей, то на каждом канале будет формироваться карта признаков, размером:
128-2 х 128-2 = 126х126
Это не самый лучший вариант. Нам бы хотелось иметь выходной размер, равный входному. Для этого, центр маски преобразования следует поместить над самым первым пикселом изображения, а ячейки ядра, выходящие за границы, заполнять некоторыми значениями, часто нулевыми:
Тогда выходные размеры карты признаков будут в точности равны исходным размерам изображения (конечно, если шаг смещения маски равен один пиксел). Если шаг смещения (stride
) увеличить и сделать равный 2, то выходные размеры карты признаков на каждом канале будут в 2 раза меньше размеров исходного изображения:
128:2 х 128:2 = 64 х 64
Какой именно шаг выбирать – зависит от конкретной решаемой задачи и желаний разработчика архитектуры СНС. Четких рекомендаций здесь нет.
Немного истории
В 1957 году Фрэнк Розенблатт изобрёл вычислительную систему «Марк-1», которая стала первой реализацией перцептрона. Этот алгоритм тоже использует интерпретацию линейного классификатора и функцию потерь, но на выходе выдаёт либо 0, либо 1, без промежуточных значений.
Индикаторы и переключатели «Марк I»
На вход перцептрона подаются веса w и исходные данные x, а их произведение корректируется смещением b.
В 1960 году Бернард Уидроу и Тед Хофф разработали однослойную нейросеть ADALINE и её улучшенную версию — трёхслойную MADALINE. Это были первые глубокие (для того времени) архитектуры, но в них ещё не использовался метод обратного распространения ошибки.
ADALINE
Алгоритм backpropagation появился в 1986 году в работе Дэвида Румельхарта, которая называлась «Многослойный перцептрон». В нём используются уже знакомые нам уравнения, правило дифференцирования и выходные значения в диапазоне от 0 до 1.
Затем в развитии машинного обучения начался период застоя, поскольку компьютеры того времени были не пригодны для создания масштабных моделей. В 2006 году Джеффри Хинтон и Руслан Салахутдинов опубликовали статью, в которой показали, как можно эффективно обучать глубокие нейросети. Но даже тогда они пока не приобрели современный вид.
Первых по-настоящему впечатляющих результатов исследователи искусственного интеллекта достигли в 2012 году, когда почти одновременно появились успешные решения задач распознавания речи и классификации изображений. Тогда же была представлена первая свёрточная нейросеть AlexNet, которая достигла высокой на тот момент точности классификации датасета ImageNet. С тех пор подобные архитектуры довольно широко применяются в разных областях.
Принцип работы CNN
Свертка — фактически главное, что необходимо понять о сверточных нейронных сетях. Этот замысловатый математический термин нужен для движущегося окна или фильтра по исследуемому изображению. Перемещающееся окно применяется к определенному участку узлов, как показано ниже. Где примененный фильтр — ( 0.5 * значение в узле):
На диаграмме показаны только два выходных значения, каждое из которых отображает входной квадрат размера 2×2. Вес отображения для каждого входного квадрата, как ранее упоминалось, равен 0.5 для всех четырех входов (inputs). Поэтому выход может быть посчитан так:
В сверточной части нейронной сети можно представить, что такой движущийся 2 х 2 фильтр скользит по всем доступным узлам или пикселям входного изображения. Такая операция может быть проиллюстрирована с использованием стандартных диаграмм узлов нейронных сетей:
Первое положение связей движущегося фильтра показано синей линией, второе — зеленой. Веса для каждых таких соединений равны 0.5.
Вот несколько вещей в сверточном шаге, которые ускоряют процесс тренировки, сокращая количество параметров, весов:
- Редкие связи — не каждый узел в первом (входном) слое соединен с каждым узлом во втором слое. Этим отличается архитектура CNN от полностью связанной нейронной сети, где каждый узел соединен со всем другими в следующем слое.
- Постоянные параметры фильтра. Другими словами, при движении фильтра по изображению одинаковые веса применяются для каждого 2 х 2 набора узлов. Каждый фильтр может быть обучен для выполнения специфичных трансформаций входного пространства. Следовательно, каждый фильтр имеет определенный набор весов, которые применяются для каждой операции свертки. Этот процесс уменьшает количество параметров. Нельзя говорить, что любой вес постоянен внутри отдельного фильтра. В примере выше веса были [0.5, 0.5, 0.5, 0.5], но ничего не мешало им быть и [0.25, 0.1, 0.8, 0.001]. Выбор конкретных значений зависит от обучения каждого фильтра.
Эти два свойства сверточных нейронный сетей существено уменьшают количество параметров для тренировки, по сравнению с полносвязными сетями.
Следующий шаг в структуре CNN — прохождение выхода операции свертки через нелинейную активационную функцию. Речь идет о некотором подвиде ReLU, который обеспечивает известное нелинейное поведение этой нейронной сети.
Процесс, использующийся в сверточном блоке, называется признаковым отображением (feature mapping). Название основано на идее, что каждый сверточный фильтр может быть обучен для поиска различных признаков в изображении, которые затем могут быть использованы в классификации. Перед разговором о следующем свойстве CNN, называемом объединением (pooling), рассмотрим идею признакового отображения и каналов.
Нейросети повсюду
Свёрточные сети хорошо справляются с огромными наборами данных и эффективно обучаются на графических процессорах за счёт параллельных вычислений. Эти особенности стали ключом к тому, что в настоящее время искусственный интеллект используется практически везде. Он решает задачи классификации и поиска изображений, обнаружения объектов, сегментации, а также применяется в более специализированных областях науки и техники.
Примеры задач классификации и поиска изображений
Примеры детектирования объектов и сегментации
Нейросети активно развиваются и уже используются в автономных автомобилях, в задачах распознавания лиц, классификации видео, определения позы или жестов человека. Кстати, именно свёрточные архитектуры научились обыгрывать людей в шахматы и . Среди других специфичных применений — анализ медицинских изображений, сегментация географических карт, составление текстового описания по фото (Image captioning) и перенос стиля художников на фотографии.
Примеры переноса стиля
Эта лишь малая часть примеров использования свёрточных сетей. Давайте разберёмся, как они работают и что делает их такими разносторонними.
Отображение признаков и мультиканальность
Поскольку веса отдельных фильтров остаются постоянными, будучи примененными на входных узлах, они могут обучаться выбирать определенные признаки из входных данных. В случае изображений, архитектура способна учиться различать общие геометрические объекты — линии, грани и другие формы исследуемого объекта. Вот откуда взялось определение признакового отображения. Из-за этого любой сверточный слой нуждается в множестве фильтров, которые тренируются детектировать различные признаки. Следовательно, необходимо дополнить предыдущую диаграмму движущегося фильтра следующим образом:
Теперь в правой части рисунка можно видеть несколько сложенных (stacked) выходов операции свертки. Их несколько, потому что существует несколько обучаемых фильтров, каждый из которых производит собственный 2D выход (в случае 2D изображения). Такое множество фильтров часто в глубоком обучении часто называют каналами. Каждый канал должен обучаться для выделения на изображении определенного ключевого признака. Выход сверточного слоя для черно-белого изображения, как в датасете MNIST, имеет 3 измерения — 2D для каждого из каналов и еще одно для их числа.
Если входной объект мультиканальный, то в случае цветного RGB изображения (один канал для каждого цвета) выход будет четырехмерным. К счастью, любая библиотека глубокого обучения, включая PyTorch, легко справляется с отображением. Наконец, не стоит забывать, что операция свертки проходит через активационную функцию в каждом узле.
Следующая важная часть сверточных нейронных сетей — концепция, называемая пулингом.
Как устроены свёрточные сети
На прошлой лекции мы обсудили идею создания полносвязных линейных слоёв. Предположим, что у нас есть исходное 3D-изображение 32x32x3. Растянем его в один длинный вектор 3072×1 и перемножим с матрицей весов размером, для примера, 10×3072. В итоге нам нужно получить активацию (вывод с оценками классов) — для этого берём каждую из 10 строк матрицы и выполняем скалярное произведение с исходным вектором.
В результате получим число, которое можно сравнить со значением нейрона. В нашем случае получится 10 значений. По этому принципу работают полносвязные слои.
Основное отличие свёрточных слоёв в том, что они сохраняют пространственную структуру изображения. Теперь мы будем использовать веса в виде небольших фильтров — пространственных матриц, которые проходят по всему изображению и выполняют скалярное произведение на каждом его участке. При этом размерность фильтра (не путать с размером) всегда соответствует размерности исходного снимка.
В результате прохода по изображению мы получаем карту активации, также известную как карта признаков. Этот процесс называется пространственной свёрткой — более подробно о нём можно почитать в статье Свёртка в Deep Learning простыми словами. Из неё вы также можете узнать, почему размер карты активации получается меньше, чем у исходной фотографии.
К изображению можно применять множество фильтров и получать на выходе разные карты активации. Так мы сформируем один свёрточный слой. Чтобы создать целую нейросеть, слои чередуются друг за другом, а между ними добавляются функции активации (например, ReLU) и специальные pooling-слои, уменьшающие размер карт признаков.
Рассмотрим подробнее, что же представляют собой свёрточные фильтры. В самых первых слоях они обычно соотносятся с низкоуровневыми признаками изображения, например, с краями и границами. В середине присутствуют более сложные особенности, такие как углы и окружности. И в финальных слоях фильтры уже больше напоминают некие специфичные признаки, которые можно интерпретировать более широко.
Примеры фильтров для свёрточных слоёв нейросети VGG-16
На рисунке ниже показаны примеры фильтров 5×5 и карты активации, которые получаются в результате их применения к исходному изображению (в левом верхнем углу). Первый фильтр (обведён в красную рамку) похож на небольшой участок границы, наклонённой вправо. Если мы применим его к фотографии, то наиболее высокие значения (белого цвета) получатся в тех местах, где есть края примерно с такой же ориентацией. В этом можно убедиться, посмотрев на первую карту активации.
Таким образом, один слой нейросети находит наиболее похожие на заданные фильтры участки изображения. Этот процесс очень похож на обычную свёртку двух функций. Она показывает, насколько объекты коррелируют друг с другом.
Сложив всё вместе, мы получим примерно следующую картину: взяв исходную фотографию, мы проводим её через чередующиеся свёрточные слои, функции активации и pooling-слои. В самом конце мы используем обычный полносвязный слой, соединённый со всеми выводами, который показывает нам итоговые оценки для каждого класса.
Схема работы свёрточной нейросети
По такому принципу работают современные свёрточные нейросети.
Особенности CNN
Полностью соединенная нейросеть с несколькими слоями может много, но чтобы показать действительно выдающиеся результаты в задачах классификации, необходимо идти глубже. Другими словами, требуется использовать намного больше слоев в сети. Однако, добавление многих новых слоев влечет проблемы. Во-первых, сталкиваемся с проблемой забывания градиента, хотя это и можно решить при помощи чувствительной функции активации — семейства ReLU функций. Другая проблема с глубокими полностью соединенными сетями — количество весов для тренировки быстро растет. Это означает, что процесс тренировки замедляется или становится практически невыполнимым, а модель может переобучаться. Тем не менее, решение есть.
Сверточные нейронные сети пытаются решить вторую проблему, используя корреляции между смежными входами в картинках или временных рядах. Например, на картинке с котиком и собачкой пиксели, близкие к глазам котика, более вероятно будут коррелировать с расположенными рядом пикселями на его носу, чем с пикселями носа собаки на другой стороне картинки. Это означает, что нет необходимости соединять каждый узел с каждым в следующем слое. Такой прием уменьшает количество весовых параметров для тренировки модели. CNN также имеют и другие особенности, улучшающие процесс тренировки, которые будут рассмотрены в других главах.
Слой подвыборки (пулинга)
Данный слой позволяет уменьшить пространство признаков, сохраняя наиболее важную информацию. Существует несколько разных версий слоя пулинга, среди которых максимальный пулинг, средний пулинг и пулинг суммы. Наиболее часто используется именно слой макспулинга.
Слою подвыборки требуется всего один гиперпараметр — шаг пулинга, то есть число раз, в которое нужно сократить пространственные размерности. Наиболее часто используется слой макспулинга с уменьшением размера входного тензора в два раза. Некоторые библиотеки позволяют задавать раздельные параметры уменьшения по высоте и ширине, однако чаще всего эти параметры совпадают.
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%.
Прямое распространение сигнала
Описав создание слоя, перейдём к написанию прямого распространения. Для получения выходного тензора необходимо пройтись по всем подматрицам размера scale x scale входного объёма, найти максимум в них и записать его в выходной тензор:
// прямое распространение Tensor MaxPoolingLayer::Forward(const Tensor &X) { Tensor output(outputSize); // создаём выходной тензор // проходимся по каждому из каналов for (int d = 0; d max) max = value; // обновляем максимум } } output(d, i / scale, j / scale) = max; // записываем в выходной тензор найденный максимум } } } return output; // возвращаем выходной тензор }
Реализация CNN на PyTorch
Любой достойный фреймворк глубокого обучения может с легкостью справиться с операциями сверточной нейросети. PyTorch является таким фреймворком. В данном разделе будет показано, как создавать CNN с помощью PyTorch шаг за шагом. В идеале вы должны обладать некоторым представлением о PyTorch, но это не обязательно. Мы хотим разработать нейронную сеть для классификации символов в датасете MNIST. Полный код к этому туториалу находится в этом репозитории на GitHub.
Мы собираемся реализовать следующую архитектуру сверточной сети:
В самом начале на вход подаются черно-белые представления символов размером 28х28 пикселей каждое. Первый слой состоит из 32 каналов сверточных фильтров размера 5х5 + активационная функция ReLU, затем идет 2х2 max pooling с даунсемплингом с шагом 2 (этот слой выводит данные размером 14х14). На следующий слой подается выход с первого слоя размера 14х14, который сканируется снова 5х5 сверточными фильтрами с 64 каналов, затем следует 2х2 max pooling с даунсемплингом для генерирования выхода размером 7х7.
После сверточной части сети следует:
- операция выравнивания, которая создает 7х7х64=3164 узлов
- средний слой из 1000 полносвязных улов
- операция softmax над крайними 10 узлами для генерирования вероятностей классов.
Эти слои представлены в выходном классификаторе.
Введение
На прошлом занятии мы научились разрабатывать глубокие нейронные сети, которые способны классифицировать изображения элементов одежды из набора данных 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=’sparce_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)
Давайте рассмотрим их подробнее.
Stride
Другим гиперпараметром, который мы можем указать в сверточном слое, является шаг, который указывает количество шагов, в которые перемещается окно фильтра (в предыдущем примере шаг был один).
Большие значения шага уменьшают размер информации, которая будет передана следующему слою. На следующем рисунке мы можем видеть тот же предыдущий пример, но теперь со значением шага 2:
(источник)
Как мы видим, изображение 5 × 5 стало меньшим фильтром 2 × 2. Но в действительности сверточные шаги по уменьшению размеров редко используются на практике; для этого используются операции объединения, которые мы представили ранее. В Keras шаг в слое Conv2D настроен с аргументом шага, который по умолчанию равеншагает = (1,1)значение, которое отдельно указывает на прогресс в двух измерениях.
Полносвязный слой
Данный слой содержит матрицу весовых коэффициентов и вектор смещений и ничем не отличается от такого же слоя в обыкновенной полносвязной сети. Единственным гиперпараметром слоя является количество выходных значений. При этом результатом применения слоя является вектор или тензор, у которого матрицы в каждом канале имеют размер 1х1. Подробнее о работе слоя можно посмотреть в статье про создание нейронной сети прямого распространения.
Полносвязный слой
Слой активации
Данный слой представляет из себя некоторую функцию, которая применяется к каждому числу входного изображения. Наиболее часто используются такие функции активации, как ReLU, Sigmoid, Tanh, LeakyReLU. Обычно активационный слой ставится сразу после слоя свёртки, из-за чего некоторые библиотеки даже встраивают ReLU функцию прямо в свёрточный слой. Подробнее про функции активации можно почитать здесь: функции активации.
Функции активации
Общий взгляд
Ниже представлено изображение из Википедии, которое показывает структуру полностью разработанной сверточной нейронной сети:
Если смотреть на рисунок сверху слева направо, сначала мы видим изображение робота. Далее серия сверточных фильтров сканирует входное изображение для отображения признаков. Из выходов этих фильтров операции пулинга выбирают подвыборку. После этого идет следующий набор сверток и пулинга на выходе из первого набора операций пулинга и свертки. Наконец, на выходе нейросети находится прикрепленный полносвязный слой, смысл которого нуждается в объяснении.
Полносвязный слой
Ранее обсуждалось, сверточная нейронная сеть берет данные высокого разрешения и эффективно трансформирует их в представления объектов. Полносвязный слой может рассматриваться как стандартный классификатор над богатым информацией выходом нейросети для интерпретации и финального предсказания результата классификации. Для прикрепления полносвязного слоя к сети измерения выхода CNN необходимо «расплющить».
Рассматривая предыдущую диаграмму, на выходе имеем несколько каналов x x y тензоров/матриц. Эти каналы необходимо привести к одному (N x 1) тензору. Возьмем пример: имеем 100 каналов с 2х2 матрицами, отображающими выход последней пулинг операции в сети. В PyTorch можно легко осуществить преобразование в 2х2х100 = 400 строк, как будет показано ниже.
Теперь, когда основы сверточных нейронных сетей заложены, настало время реализовать CNN с помощью PyTorch.