Сможет ли сеть, обученная на поддельных данных, распространиться на реальный мир?

Лорен Хольцбауэр была научным сотрудником программы Insight летом 2018 года.

Сегодня я дважды не думаю о том, чтобы пойти в какой-либо тренажерный зал, оценить оборудование и провести вместе действительно хорошую тренировку, но так было не всегда. Первый раз я вошел в тренажерный зал шесть лет назад, когда был в Калифорнийском университете в Лос-Анджелесе. Место кишело разъяренными братьями, и единственным доступным оборудованием была эта странно выглядящая штука в углу. Позже той ночью я обнаружил, что гуглил: «Треугольник подушки платформы для ног по диагонали тренажерного зала». Потребовалось несколько недель поиска в Google, чтобы наконец понять, что это называется гиперэкстензионной скамьей.

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

В этом посте я расскажу, как я построил классификатор изображений для этого проекта, используя две разные реализации сверточных нейронных сетей (CNN). Я также расскажу, как я справлялся с конкретными проблемами при сборе данных. Присмотритесь к трем изображениям жима лежа выше. Вам что-нибудь кажется подозрительным…? Читай дальше, чтобы узнать больше!

Зачем использовать CNN?

Сети CNN широко считаются новейшими инструментами компьютерного зрения с 2012 года, когда AlexNet выиграл конкурс ImageNet Large Scale Visual Recognition Challenge (ILSVRC) ».

CNN особенно подходят для работы с изображениями, потому что:

  • Они сохраняют пространственную информацию, принимая двумерный массив в качестве входных данных. Чтобы отправить изображение через обычную сетевую сеть, вам нужно будет сгладить его в одномерный массив.
  • Они предотвращают разнесение весов через частично связанные слои (сверточные и объединяющие слои).
  • Они могут обнаружить один и тот же объект в любом месте изображения. Ванильный NN может обнаруживать только те элементы, которые находятся в идентичных позициях на изображении.
  • Они иерархически структурированы, аналогично тому, как мозг животных обрабатывает изображения. Эта структура позволяет повторно использовать одну и ту же сеть (т.е. «предварительно обученную» модель) для множества различных задач. Ниже мы рассмотрим, как создать предварительно обученную сеть!

Для более глубокого погружения в механику CNN ознакомьтесь с моим предыдущим сообщением Объяснение сверточных нейронных сетей… с американским воином ниндзя.

Данные: создание тренировочного набора с плавучим тренажерным оборудованием.

Вызов принят: что делать, если у вас недостаточно данных

Сетевым сетям просто нужно МНОГО обучающих данных, чтобы выучить осмысленные шаблоны. Это одна из причин, почему глубокие CNN не обучались успешно до конца 2000-х; Только после того, как Интернет стал взрывным, у исследователей было достаточно изображений для составления очень больших наборов обучающих данных. Это означало, что мне понадобится много-много фотографий тренажерного зала, чтобы тренировать мой классификатор изображений.

Я остановился на пяти классах оборудования:

  1. жим лежа
  2. скамья для гиперэкстензии
  3. плиометрическая коробка
  4. жим ногами
  5. силовая стойка

Я поставил цель получить примерно 1000 изображений для каждого класса и начал прочесывать Google Images. Ниже показаны некоторые результаты моего первоначального поиска:

Я предполагал, что собрать много фотографий спортивного оборудования будет довольно просто. Неправильный! Хотя изображения, которые я собрал, имели хорошие вариации в ориентации объекта, не было вообще никаких изменений в фоне: все изображения имели простой белый фон. Это было большой проблемой, поскольку для создания хорошего классификатора изображений необходимо снабдить его как можно большим количеством примеров, чтобы он мог хорошо обобщаться. Вдобавок к этому у меня было всего от 40 до 50 уникальных изображений для каждого класса.

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

Какого черта! Давайте обучим CNN фальшивыми данными!

Я был знаком со стратегией использования методов увеличения данных (таких как переворачивание, срезание, масштабирование и т. Д.) Для искусственного увеличения размера обучающего набора данных (посмотрите этот соответствующий Средний пост и этот тоже!) , но я задавался вопросом, сможет ли CNN по-прежнему учиться на изображениях, которые были еще более радикально расширены ... до такой степени, что они ... полностью поддельные!

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

Я решил использовать что-то под названием Pillow для последующих задач обработки изображений. Pillow - это ответвление библиотеки изображений Python (PIL), аналогичное OpenCV. Вы можете просмотреть документацию и ознакомиться с кратким учебником.

Чтобы массово генерировать смоделированные изображения, я построил конвейер с Pillow, который:

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

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

Я скопировал более 150 изображений интерьеров спортзалов из Google Images и объединил случайное подмножество из 25 из них с каждым изображением тренажерного зала. Я отправил каждую пару передний план-фон через конвейер, в результате чего было создано более 5 400 смоделированных изображений!

Дополнительное увеличение изображения с помощью Keras

Я решил реализовать свои классификаторы изображений для этого проекта с помощью Keras. Keras - это API глубокого обучения с открытым исходным кодом, написанный на Python и работающий поверх Tensorflow, поэтому он немного более удобный и высокоуровневый, чем Tensorflow. Ознакомьтесь с документацией Keras здесь.

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

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

Теперь, когда мы сгенерировали смоделированные изображения, мы готовы ответить на очень интересный вопрос: может ли CNN учиться на «фальшивых» данных? Давайте попробуем две очень разные реализации CNN и посмотрим, какая из них победит!

Два CNN сражаются! В этом углу… Реализация №1: CNN построен с нуля

Первой реализацией, которую я попробовал, была CNN, созданная и обученная с нуля. Эта CNN имеет восемь уровней: три сверточных слоя (за каждым следует уровень активации ReLU и максимальный уровень объединения), затем два полностью связанных слоя. Последний полностью связанный слой (выходной слой) имеет активацию softmax. Обратите внимание: поскольку у нас есть пять классов, выходной слой имеет пять нейронов. Архитектура представлена ​​ниже. Вы могли заметить, что эта архитектура очень похожа на LeNet-5.

Каждый сетевой слой на изображении выше помечен своим типом (вверху) и размером выходного изображения (внизу). Размер входного изображения был изменен до 150x150 пикселей и преобразован в оттенки серого. Сохранение всех трех каналов RGB из исходного цветного изображения увеличит количество весов, которые сеть должна будет изучить, и увеличит время обучения. Обратите внимание, как изображение становится меньше и глубже по мере прохождения по сети. Первый сверточный слой выводит 32 карты объектов размером 148x148 пикселей, а последующий слой объединения уменьшает размер каждой карты до 74x74 пикселей.

Взгляните на реализацию Keras нашего CNN с нуля ниже.

Код Keras очень интуитивно понятен. Давайте рассмотрим приведенный выше пример кода:

Сверточные слои

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

Полностью подключенный и выходной слои

Четвертый блок кода реализует последние 2 полносвязных слоя. В этом блоке мы сначала сглаживаем выходной тензор из последнего слоя объединения. Это просто означает, что мы преобразуем тензор из ранга 3 в ранг 1. Тензор ранга 1 в основном представляет собой одномерный массив, но помните, что технически это тензор, а не массив. Вот почему они называют это Tensorflow! Ознакомьтесь с этой замечательной средней статьей, в которой обсуждается разница между тензорами и многомерными массивами.

Сглаженный тензор затем передается в первый полностью связанный слой (принадлежащий классу Dense в Keras). Затем применяется активация ReLU, за которой следует нечто, называемое выпадением. Так же, как Lasso и Ridge - это методы регуляризации, которые можно применять к моделям линейной регрессии, отсев можно применять к нейронным сетям для предотвращения переобучения. Узнайте больше о том, как бросить учебу, в этой отличной, углубленной дискуссии CNN.

Последний слой плотный служит выходным слоем; мы назначаем ему то же количество нейронов, что и количество классов (в нашем случае мы хотим различать 5 классов тренажерного зала, поэтому мы используем 5 нейронов). Активация softmax преобразует исходное выходное значение для каждого нейрона в вероятность, поэтому мы получаем оценку вероятности 1 для каждого класса. Класс с наибольшей вероятностью становится победителем.

Выбор функции потерь и оптимизатора

Наконец, в последнем блоке кода мы должны скомпилировать только что построенную модель. Мы передаем 3 параметра: потери, оптимизатор и метрики. Функция loss просто относится к функции стоимости, которая является некоторым функциональным представлением ошибки (все функции loss, которые поддерживает Keras, можно найти здесь). Цель здесь - оптимизировать веса таким образом, чтобы потери были сведены к минимуму. оптимизатор - это алгоритм, который точно определяет, как настроить веса для каждого шага во время обратного распространения ошибки. В линейной регрессии потеря - это среднеквадратическая ошибка, а оптимизатор - градиентный спуск.

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

За прошедшие годы было разработано множество оптимизаторов, улучшающих градиентный спуск. Оптимизаторы адаптивного обучения сохраняют в памяти градиенты из предыдущих шагов и сравнивают их с градиентом на текущем шаге. Это позволяет им понять, когда они приближаются к дну чаши, в какой момент они замедляются и делают более мелкие шаги. Несколько оптимизаторов адаптивного обучения, которые хорошо работают на практике, - это Adadelta, RMSprop и Adam. Однако определение того, какой из них использовать, может быть больше искусством, чем наукой. Если вы хотите узнать больше обо всех различных оптимизаторах, ознакомьтесь с этой отличной статьей о Medium и этой чудесно подробной записью в блоге.

Выбор метрики оценки

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

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

В этом углу… Реализация №2: «Передача обучения» с VGG16

Как работает трансферное обучение?

Для нашей второй реализации классификатора спортивного оборудования мы собираемся использовать VGG16 (или… его часть). Архитектура VGG16 заняла второе место в конкурсе ILSVRC-2014. VGG16 был разработан Visual Geometry Group (VGG) в Оксфорде. Он был обучен на подмножестве набора данных ImageNet, который является крупнейшей и наиболее полной в мире базой данных изображений с ручными аннотациями. ImageNet содержит более 14 миллионов изображений, которые попадают в более чем 20 000 категорий. Все претенденты на ILSVRC-2014 прошли обучение на подмножестве ImageNet, которое содержало 1000 из общего количества 20 000 категорий. Категории 1000 включали все, от собак до пианино и космических шаттлов (полный список можно найти здесь).

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

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

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

Обзор архитектуры VGG16

VGG16 имеет 16 слоев, не включая слои объединения и выходной слой. Его архитектура считается одной из самых простых из всех современных CNN, особенно по сравнению с такими архитектурами, как GoogleNet и ResNet. На изображении ниже вы можете видеть, что одно из основных различий между VGG16 и LeNet-5 заключается в том, что VGG16 складывает сверточные слои один поверх другого, вместо того, чтобы следовать за каждым слоем объединения.

Слои, помеченные выше со снежинками, «заморожены». Это слои, которые мы собираемся переработать. Обратите внимание, как все заморожено, кроме полностью связанных слоев. При построении новой сети мы повторно используем замороженные слои из VGG16 и построим 2 полностью связанных слоя поверх них. Когда мы обучаем новую сеть, веса для переработанных слоев останутся замороженными во время обратного распространения, в то время как веса для незамороженных слоев будут настроены и оптимизированы.

Реализация предварительно обученной модели

Давайте посмотрим на код, чтобы увидеть, как выглядит реализация!

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

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

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

Начнем с первой части. Еще одна причина, по которой Keras настолько удобен, заключается в том, что вы можете легко создавать экземпляры предварительно загруженных моделей, таких как VGG16. В строке 8 мы создаем замороженные слои VGG16, передав параметры 2 в applications.VGG16 ():

  1. include_top = False, что исключает «верхние» слои (полностью связанные слои) и
  2. weights = ’imagenet’, который загружает веса, которые были обучены в наборе данных ImageNet.

Мы отправляем входные данные через эти замороженные слои в строке 11 и сохраняем выходные данные в переменной bottleneck_prediction. Этот выход будет входом для второй части сети.

В строках 14–18 мы реализуем вторую часть сети: автономную сеть с 2 полносвязными слоями, включая выходной слой. В строке 21 мы загружаем веса, которые мы ранее обучили для этих верхних слоев и сохранили в файле с именем «top_model_weights.h5». Наконец, мы передаем bottleneck_prediction в model.predict_classes (), чтобы сделать окончательный прогноз.

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

Как мы обсуждали ранее, VGG16 был обучен более чем 1000 категориям изображений, включая далматинцев, космических кораблей и фортепиано. Из этих 1000 категорий только одна («гантели») попала в более широкую категорию спортивного оборудования и не похожа ни на один из наших 5 классов. . Я скептически относился к тому, будет ли эта реализация работать. В следующем разделе мы узнаем!

И победитель…

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

Чтобы оценить это, я собрал набор из более чем 100 реальных изображений тренажерного зала. Некоторые из этих изображений показаны ниже. Каждое изображение помечено парой флажков, указывающих, было ли оно правильно классифицировано (зеленая галочка) или ошибочно (красная отметка) каждой опробованной нами моделью. Проверка слева соответствует реализации №1 (CNN-с нуля), а проверка справа соответствует реализации №2 (предварительно обученная сеть).

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

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

И победителем становится… предварительно обученная сеть! CNN с нуля достигла общей точности 85% на реальной проверке, в то время как предварительно обученная сеть достигла точности 92%. Я был удивлен, насколько хорошо работала предварительно обученная модель. VGG16 был обучен на таком огромном наборе данных, что изучил множество функций низкого и среднего уровня. Эти функции достаточно универсальны, чтобы мы могли использовать их для эффективной классификации спортивного оборудования, даже несмотря на то, что VGG16 не обучался на каких-либо изображениях спортивного оборудования!

Резюме

Надеюсь, вам понравилось ходить в спортзал с CNN! В этом посте мы опробовали две реализации классификатора тренажерного зала и обнаружили удивительную способность трансферного обучения. Мы реализовали классификатор спортивного оборудования, используя CNN, созданную с нуля, и CNN, в которой использовалось трансферное обучение. Реализация трансферного обучения достигла на 7% большей точности, чем реализация с нуля.

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

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

Так что в следующий раз, когда вы пойдете в спортзал, не забудьте свой CNN!

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