Распознавание дорожных знаков с помощью CNN: Spatial Transformer Networks |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2017-10-06 11:55 обучение нейронной сети, техническое зрение, методы распознавания образов Привет, Хабр! Продолжаем серию материалов от выпускника нашей программы Deep Learning, Кирилла Данилюка, об использовании сверточных нейронных сетей для распознавания образов — CNN (Convolutional Neural Networks).
В прошлом посте мы начали разговор о подготовке данных для обучения сверточной сети. Сейчас же настало время использовать полученные данные и попробовать построить на них нейросетевой классификатор дорожных знаков. Именно этим мы и займемся в этой статье, добавив дополнительно к сети-классификатору любопытный модуль — STN. Датасет мы используем тот же, что и раньше. Spatial Transformer Network (STN) — один из примеров дифференцируемых LEGO-модулей, на основе которых можно строить и улучшать свою нейросеть. STN, применяя обучаемое аффинное преобразование с последующей интерполяцией, лишает изображения пространственной инвариантности. Грубо говоря, задача STN состоит в том, чтобы так повернуть или уменьшить-увеличить исходное изображение, чтобы основная сеть-классификатор смогла проще определить нужный объект. Блок STN может быть помещен в сверточную нейронную сеть (CNN), работая в ней по большей части самостоятельно, обучаясь на градиентах, приходящих от основной сети. Весь исходный код проекта доступен на GitHub по ссылке. Оригинал этой статьи можно посмотреть на Medium. Чтобы иметь базовое представление о работе STN, взгляните на 2 примера ниже: STN работает даже в сложных случаях (например, 2 знака на изображении), но самое главное — STN действительно улучшает качество классификатора (IDSIA в моем случае). Общее устройство STN: курс молодого бойца Одна из проблем сверточных нейронных сетей — слишком низкая инвариантность к входным данным: разный масштаб, точка съемки, шум на заднем плане и многое другое. Можно, конечно, сказать, что операция пулинга, так не любимая Хинтоном, дает некоторую инвариантность, но фактически она просто уменьшает размер feature map, что выливается в потерю информации.К сожалению, из-за маленького рецептивного поля в стандартном 2х2 пулинге пространственная инвариантность может быть достигнута лишь в глубоких слоях, близких к output-слою. Также пулинг не обеспечивает инвариантность вращения и масштаба. Кевин Закка хорошо объяснил причину этого в своем посте. Основной и самый распространенный способ сделать модель устойчивой к этим вариациям — аугментация датасета, что мы и сделали в предыдущей статье: Аугментированные изображения. В этом посте мы не будем использовать аугментацию. В таком подходе нет ничего плохого, но нам бы хотелось разработать более умный и автоматизированный метод предобработки изображений, который должен способствовать увеличению точности классификатора. Spatial transformer network (STN) — как раз то, что нам нужно. Ниже еще один пример работы STN: Пример из датасета MNIST из статьи-первоисточника. Cluttered MNIST (слева), целевой объект, распознанный STN (центр), преобразованное изображение (справа). Работа STN модуля может быть сведена к следующему процессу (не включая обучение): Применение STN преобразования в 4 шага при известной матрице линейных преобразований ?. Теперь рассмотрим подробнее этот процесс и каждый его этап. STN: этапы преобразования Шаг 1. Определить матрицу преобразований ?, которая описывает саму трансформацию:Аффинное преобразование матрицы ?. При этом каждому преобразованию соответствует своя матрица. Нас интересуют следующие 4:
Шаг 2. Вместо того, чтобы применять преобразование напрямую к исходному изображению (U), создадим выборочную сетку (sampling meshgrid) того же размера, что и U. Выборочная сетка — это набор индексов (x_t, y_t), которые покрывают исходное пространство изображений. Сетка не содержит в себе никакой информации о цвете изображений. Лучше это объясняется в коде ниже:
Поскольку это фактическая имплементация в TensorFlow, чтобы понять общую идею, переведем этот код в аналог на numpy:
Шаг 3. Применить матрицу линейных преобразований к созданной выборочной сетке, чтобы получить новый набор точек на сетке, каждая из которых может быть определена как результат умножения матрицы ? на вектор координат (x_t, y_t) со свободным членом: Шаг 4. Получить подвыборку V, используя исходную карту признаков, преобразованную выборочную сетку (см. Шаг 3) и дифференцируемую функцию интерполяции на ваш выбор (например, билинейная). Интерполяция необходима, так как нам нужно перевести результат сэмплинга (потенциально возможные дробные значения пикселей) в целые числа. Сэмплинг и интерполяция Задача обучения. Говоря в общем, если бы мы заранее знали нужные нам значения ? для каждого исходного изображения, можно было бы начинать описанный выше процесс. На деле же, нам бы хотелось извлекать ? из данных с помощью машинного обучения. Это сделать вполне реально. Во-первых, нам нужно убедиться, что функция потерь классификатора дорожных знаков может быть минимизирована с помощью backprop через сэмплер. Во-вторых, мы находим градиенты по U и G (meshgrid): именно поэтому функция интерполяции должна быть дифференцируема или, хотя бы, частично дифференцируема. В-третьих, рассчитываем частные производные x и y по ?. Технические выкладки можно прочитать в исходной пейпе. Наконец, мы создаем LocNet (локализующая сеть-регрессор), единственной задачей которой будет обучиться и спрогнозировать корректные ? для принимаемого на вход изображения, используя функцию потерь, которая была минимизирована через общий backprop. Главное достоинство такого подхода заключается в том, что мы получаем дифференцируемый автономный модуль с памятью (в виде обучаемых весов), который может быть помещен в любую часть CNN. Заметьте, как меняется ?, пока STN обучается распознавать целевой объект (дорожный знак) на изображениях. Ниже представлена схема работы STN из оригинальной статьи: Мы рассмотрели все этапы построения STN: создание LocNet, генератора выборочной сетки (meshgrid) и сэмплера. Теперь построим и обучим на TensorFlow весь классификатор, который включает в свой граф и STN. Построение модели в TensorFlow Весь код модели, конечно, не уместится в рамки одной статьи, но он доступен в виде Jupyter-ноутбука в репозитории на GitHub.В этой же статье я акцентирую внимание на некоторых важных частях кода и этапах обучения модели. Во-первых, наша конечная цель — научиться распознавать дорожные знаки, и для ее достижения нам нужно создать какой-то классификатор и обучить его. Вариантов у нас много: от LeNet и до любой другой SOTA-нейросети. В процессе работы над проектом, вдохновившись работой Moodstocks по STN (реализованной в Torch), я использовал архитектуру нейронной сети IDSIA, хотя ничто не мешало взять что-то другое. На втором этапе нам нужно определить и обучить STN модуль, который, принимая на вход исходное изображение, преобразует его с помощью сэмплера и на выходе получается новое изображение (или минибатч, если мы работаем в батч-режиме), которое в свою очередь используется классификатором. Отмечу, что STN можно легко убрать из графа вычислений, заменив весь модуль простым генератором батчей. В таком случае, мы просто получим обычную сеть-классификатор. Вот общая схема работы полученной двойной нейронной сети: Ниже приведена часть DAG, в рамках которого исходные изображения преобразуются с помощью STN и подаются на вход классификатору (IDSIA), который рассчитывает логиты:
Теперь, когда мы знаем метод расчета логитов (STN + IDSIA network), следующим шагом будет оптимизация функции потерь ( в качестве которой мы будем использовать кросс-энтропию или log loss — стандартный выбор для решения задачи классификации):
Затем нам нужно задать операции (ops) оптимизации и обучения, которые должны распространять ошибки обратно к входным слоям:
Я инициализировал сеть с большим значением learning rate (0.02), чтобы градиенты могли быстрее распространять информацию к LocNet STN, которая расположена во внешних слоях всей нейронной сети. В противном случае эта сеть будет обучаться медленнее (из-за проблемы «исчезающего» градиента). Маленькие исходные значения learning rate не позволяют нейросети хорошо приближать мелкие дорожные знаки на изображении. Часть DAG, которая рассчитывает логиты (выход сети) добавляется в граф довольно просто:
Кусок кода выше развертывает всю сеть — STN + IDSIA, их мы обсудим подробнее ниже. IDSIA: сеть-классификатор Вдохновленный работой Moodstocks и оригинальной статьей от IDSIA Swiss AI Group, в которой они использовали ансамбль из CNN, чтобы улучшить ранее достигнутое качество модели, я взял общую идею архитектуры одной сети из ансамбля и реализовал его в TensorFlow самостоятельно. Получившаяся структура классификатора выглядит следующим образом:
Все это проиллюстрировано ниже: На вход conv1 подается преобразованное STN изображение, как мы и обсуждали ранее. Spatial Transformers в TensorFlow Среди всего разнообразия моделей TensorFlow можно найти реализацию STN, которая и будет использована в нашей сети.Наша задача — обозначить и обучить LocNet, обеспечить transformer корректными значениями ? и вставить STN модуль в DAG Tensorflow. transformer генерирует сетку и обеспечивает преобразования и интерполяцию. Конфигурация LocNet представлена ниже: Сверточные слои LocNet:
Fully-connected часть LocNet:
Структура сверточных слоев LocNet похожа на IDSIA (хотя LocNet состоит из 2 слоев вместо 3, и в ней мы сначала делаем пуллинг). Более любопытна структура полносвязных слоев: Обучение и результаты Проблема использования STN модуля с CNN заключается в необходимости следить за тем, чтобы обе сети не переобучались, что делает процесс обучения сложным и нестабильным. С другой стороны, добавление небольшого количества аугментированных данных (особенно аугментирование яркости) в обучающую выборку позволяет сетям не переобучаться. В любом случае, преимущества перевешивают недостатки: даже без аугментации мы получаем хорошие результаты, а STN+IDSIA превосходят по точности IDSIA без этого модуля на 0,5-1%.В процессе обучения были использованы следующие параметры:
Уже после 10 эпох мы получаем точность равную 99,3% на validation наборе данных. CNN все еще переобучается, но не забывайте, что мы используем двойную сложную сетку на исходном датасете без его расширения аугментациями. По правде говоря, добавив аугментацию, мне удалось получить точность равную 99,6% на validation сете после 10 итераций (хотя значительно увеличилось время обучения). Ниже приведены результаты обучения моделей (idsia_1 — это IDSIA сеть без модуля, idsia_stn — это STN+IDSIA). Это точность всей сети на валидации. Наконец, вот результат работы STN трансформера после обучения:
Источник: habrahabr.ru Комментарии: |
|