Этот пост следует за ML intro 3 или ML intro 6. Мы предполагаем, что вы интуитивно понимаете силу наложения слоев линейной регрессии с чередующимися нелинейными функциями для создания нейронной сети, а также понимаете настраиваемые единицы вывода, такие как логистическая функция или функция softmax.

Эта лекция была написана как часть моей серии в Columbia Engineering https://bootcamp.cvn.columbia.edu/data/ и предназначена для технической и корпоративной аудитории.

Цель обучения

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

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

Постановка проблемы

Проблема заключается в том, чтобы выполнить мультиклассовую классификацию, полагаясь на блоки вывода softmax. Мультиклассовая классификация, как обсуждалось в ML intro 3, классифицирует точку данных по одному из нескольких типов. Как и в ML intro 3, мы используем модули вывода softmax для распределения вероятностей того, насколько вероятен каждый тип (или класс). Но для этого анализа мы используем изображения в качестве входных данных * gasp *.

Не спешите и погуглите «Машинное обучение для изображений» или «Как свертить тензорный поток». Скорее давайте подумаем, чего мы хотим от нашей системы машинного обучения, и спроектируем это соответствующим образом.

Код

Следуйте вместе с неразрешенным частично написанным кодом здесь: https://github.com/leedtan/LeeTanData/blob/master/ML_Intro_7_Convolutions/Unsolved.ipynb

и см. заполненное решение здесь: https://github.com/leedtan/LeeTanData/blob/master/ML_Intro_7_Convolutions/Solution.ipynb

Необработанные данные

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

То же самое и с изображениями. Каждое изображение может быть строкой, и каждое значение изображения может быть функцией в нашей модели машинного обучения. Обратите внимание, что изображения явно имеют сетчатую структуру. Изображение часто понимается как 2-мерная сетка пикселей, либо изображение в градациях серого NxN (каждый пиксель - это просто значение), либо изображение NxNx3 RGB (каждый пиксель содержит 3 значения: красный, зеленый и синий). Их можно рассматривать как 2d-сетки с 1 фильтром или 3 фильтрами, с фильтром, определенным в этом пространстве как слой числовых значений, по одному значению на пространственную область изображения. В нейронных сетях для изображений мы вычисляем слои нейронной сети, состоящие из множества фильтров, а не только из множества плотных узлов.

Давайте визуализируем одно из наших изображений в оттенках серого:

Моделирование данных изображения

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

Проверка концепции: математика изображений нейронной сети

Допустим, у нас есть изображение 1024x1024, и мы хотим вычислить скрытый слой того же размера. Сколько скалярных множителей нам нужно узнать для этого слоя?

Решение: математика изображений нейронной сети

1024 * 1024 * 1024 * 1024 скаляров, потому что каждый из миллиона входных блоков должен подключаться к каждому из миллиона выходных блоков. Это ОДИН МИЛЛИАРД изученных параметров только для одного скрытого слоя. Кажется чрезмерным, правда?

Представляем локальные подключения

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

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

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

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

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

Обратите внимание, что выходной фильтр (зеленый справа) выше меньше, чем фильтр слева.

Теперь обратите внимание, что высота и ширина синего куба и красного изображения или синего квадрата и зеленого квадрата совпадают. Посмотрите, как каждое местоположение зеленого квадрата вычисляется сеткой 3x3? Также обратите внимание, что боковые узлы вычисляются путем наблюдения за областью за пределами синей сетки. Эти пустые ячейки, используемые для сохранения размера и формы изображения, называются заполнением. Следовательно, ядру 5x5 потребуется заполнение 2 со всех сторон для сохранения размера изображения.

Проверка концепции: локальные подключения нейронной сети

Обсудите с партнером, если это будет в классе. Допустим, у нас есть изображение в оттенках серого 5x5x1, и мы хотим вычислить изображение в оттенках серого 3x3x2 без отступов. Сколько ядер нам понадобится? Как мы будем их использовать? Используйте python для генерации ядер случайным образом [-1, 0, 1] и вычисления значений скрытого слоя для следующего входного изображения:

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

Решение: локальные подключения нейронной сети

Нам нужно 18 ядер, по 2 на каждое пространственное местоположение, всего 9 пространственных местоположений.

Ниже мы случайным образом генерируем наши 18 ядер,

Умножить на вход

И обрезать отрицательные значения до 0

Создание:

Проверка концепции: количество параметров, подключенных локально

С учетом приведенной выше формулировки, сколько параметров нам нужно теперь, чтобы узнать скрытое представление из изображения в оттенках серого 1024x1024? Теперь предположим, что наш скрытый слой имеет 16 скрытых единиц, и каждая единица имеет ядро ​​3x3.

Решение: количество параметров, подключенных локально

Что ж, нам нужно приблизительно 1024x1024 местоположения для вычисления, и для каждого местоположения нам нужно узнать только 16 * 9 параметров (в отличие от 16 * 1024 для полностью подключенного слоя). Это снижает наши параметры в 100 раз! Теперь нам нужно всего 10⁸ параметров, что все равно может показаться большим количеством.

Завершение локальных подключений:

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

Введение в совместное использование пространственных параметров

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

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

Проверка концепции: пространственные параметры, совместно используемые число параметров

С учетом приведенной выше формулировки, сколько параметров нам нужно теперь, чтобы узнать скрытое представление из изображения в оттенках серого 1024x1024? Снова наш скрытый слой имеет 2 скрытых блока с тем же ядром 3x3.

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

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

Решение: Пространственные параметры, совместно использующие количество параметров

Что ж, в каждом месте изображения нам все еще нужно 2 * 9 параметров, чтобы изучить 2 фильтра, но теперь мы применяем те же 2 фильтра ко всему изображению! Теперь мы можем изучить весь фильтр всего с 2 * 9 ~ 18 параметрами!

Ниже мы случайным образом генерируем наши 2 ядра,

Умножить на вход

И обрезать отрицательные значения до 0

Создание:

Придумайте термин Слой свертки

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

Совместное использование параметров и его применение для двумерного сверточного слоя - одна из ключевых идей, сделавших Янна Лекуна (руководителя Facebook AI Research) известным и позволившим использовать большую часть ИИ, с которым мы сталкиваемся ежедневно.

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

Слои объединения:

Пул - это слои сжатия. Допустим, у меня есть изображение в оттенках серого 1024x1024x1, и я не хочу иметь дело с таким большим изображением в вычислительном отношении. Что ж, для каждого куба 4x4 я могу взять максимальное значение (или минимальное значение, или среднее значение), которое сжимает изображение в изображение в оттенках серого 256x256x1. (Для одного слоя требуется в 16 раз меньше вычислительной мощности!)

Отмена пула, напротив, расширяет изображение в пространстве, как и следовало ожидать.

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

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

Полосатые свертки:

Шаг свертки - это количество входных пространственных местоположений, сжатых в одно выходное местоположение.

Например, шаг в два уменьшит размер изображения в два раза, как при объединении 2x2. Кроме того, шаг 0,5 (также называемый транспонированной сверткой) увеличил бы размер изображения в 2 раза.

Обратите внимание, что шаг в 2 раза уменьшает форму изображения вдвое, а шаг 0,5 увеличивает ширину и высоту изображения вдвое.

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

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

Теперь давайте реализуем нейронную сеть в Pytorch.

В этом упражнении вы должны использовать nn.Conv2d, nn.LeakyReLU и nn.MaxPool2d для создания слоев нейронной сети, которые преобразуют изображение в узкое представление, подобное изображению, затем преобразовывают содержимое в один вектор и выполняют стандартную классификацию. .

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

Сначала импортируйте много пакетов

Кодирование: прочтите метки данных

Решение: прочитать этикетки с данными.

Задание по кодированию: сопоставление текстовых меток данных с числами

Решение: сопоставьте текстовые метки данных с числами

Читайте в изображениях. Загрузить из кеша, если прочитано ранее.

Вот несколько полезных функций для всех ваших проектов PyTorch

Заполните TODO вашей модели

И обучите модель, заполнив следующие TODO:

Создайте и обучите модель и нанесите на график кривую обучения

Визуализируйте свой первый слой (или второй!)

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

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

Заворачивать

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

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

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

Завершите то, что мы рассмотрели:

На протяжении этой сессии мы

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

Дополнительные сообщения для разработчиков программного обеспечения:
Подробное объяснение по математике и компьютерной науке (часть 1): https://medium.com/@leetandata/neural-network-introduction -для-инженеров-программистов-1611d382c6aa

Подробное объяснение по математике и компьютерной науке (часть 2): https://medium.com/@leetandata/neural-network-for-software-engineers-2-mini-batch-training- and-validation-46ee0a1269a0

Дополнительные математические заметки от профессора Чо:
https://github.com/nyu-dl/Intro_to_ML_Lecture_Note/raw/master/lecture_note.pdf