Целью этого проекта было использование глубоких нейронных сетей и, в частности, сверточных нейронных сетей для классификации дорожных знаков. Он реализован в TensorFlow в среде ноутбука Python.
Классификатор дорожных знаков обучается на Немецком наборе данных о дорожных знаках. Всего имеется 39209 обучающих выборок и 12630 проверочных выборок из 43 классов. Изображения имеют размер 32x32x3. Примеры каждого класса визуализируются ниже:
Образцы изображений распределены по классам, как показано ниже:
Предварительная обработка данных
В этом проекте нас попросили предварительно обработать изображения. Основной метод предварительной обработки, который я использовал, заключался в отображении изображений в оттенках серого. Я использовал этот подход, поскольку многие знаки имели схожие цветовые узоры, и, следовательно, в некоторых случаях не было никакого реального преимущества от использования цвета. Кроме того, было обнаружено, что подход в оттенках серого дает лучшие результаты, как показано в [1]. Кроме того, в своих экспериментах я также пытался сдвинуть данные к нулевому среднему, вычитая среднее значение обучающего набора из всех данных по каждому измерению. Несмотря на то, что теоретически этот подход предлагается, я обнаружил, что он работает хуже на 3–4% с точки зрения точности тестирования. Следовательно, я использовал только преобразование оттенков серого в качестве метода предварительной обработки. Я не использовал аугментацию данных и получил точность тестирования 95%. Улучшение набора данных наверняка может привести к лучшим результатам, как показано в [1].
Обучение модели
Для начала я использовал 30% своих обучающих данных для проверки. Затем я попытался использовать 20% для проверки, чтобы увеличить размер обучающих данных. Чтобы сгенерировать проверочный набор, я не выбирал случайным образом 20 % из всех обучающих данных, а скорее выбирал 20 % данных каждого класса, чтобы сделать проверочный набор более репрезентативным и протестировать для всех случаев.
Я протестировал три разные архитектуры: LeNet (функция lenet) из лаборатории и две более глубокие (функции signRecNet и signRecNet_deeper). Первый имеет 4 сверточных слоя, по два с каждой стороны слоя объединения (2 с фильтрами 5x5 и 2 с фильтрами 3x3). Вторая архитектура, которую я в конечном итоге использовал, имеет 5 сверточных слоев, каждый из которых представляет собой фильтр размером 3x3 с двумя объединяющими слоями, чтобы добиться более изящной деградации входного изображения и собрать функции в большем количестве иерархий. Вся архитектура имела одинаковое количество нейронов для полностью связанных слоев.
Окончательная архитектура, которую я использовал, выглядит следующим образом:
Начальные обучающие эксперименты с подходом к поиску по сетке со скоростью обучения 0,001 и размером пакета 256. Эти параметры были выбраны, поскольку они являются типичными значениями для обучающих консетей для распознавания изображений. Больший размер партии (вместо 64 для лаборатории LeNet) может привести к менее шумным обновлениям весов. В большинстве симуляций я запускаю эксперименты для 50 эпох, однако в последних раундах я изменил их на 100 эпох, чтобы посмотреть, можно ли сделать какое-либо улучшение. Похоже, что цель модели насыщается довольно быстро, и, следовательно, увеличение количества эпох не помогает. Однако этого следует ожидать при увеличении размера партии. Наконец, я использовал AdamOptimizer, как в LeNet Lab, так как он работает лучше, чем стандартный SGD.
В целом, процесс настройки convNet проходил методом проб и ошибок. Сначала я начал с архитектуры LeNet, изменив количество фильтров на слой. Я выполнил поиск по сетке количества фильтров для значений 8, 16 и 32. Я заметил, что по мере увеличения количества фильтров точность проверки и тестирования снижается, что может указывать на переобучение. В целом, с предварительной обработкой оттенков серого мне удалось добиться точности около 88–92% с помощью LeNet.
Для дальнейших экспериментов я пробовал разные архитектуры.
1) Сначала я использовал ConvNet, определенную в функции, состоящей из четырех сверточных слоев. Первые два сверточных слоя имели фильтры 5x5, а последний — фильтры 3x3. Это дало точность 93–94% на тестовом наборе.
2) Затем я попытался сделать сеть глубже (архитектура определена в функции), однако, чтобы постепенно уменьшать разрешение изображения, я изменил все размеры фильтров для сверточных слоев на 3x3. Это дало дополнительный прирост производительности на 1-2%.
В обоих этих случаях количество сверточных фильтров постепенно увеличивается с 8 до 16 и далее до 32. Также я использовал отсевающие слои, сначала отсев с 50% коэффициентом сохранения между ними. Во всех экспериментах я использовал одинаковое количество нейронов для полносвязных слоев ( кроме последнего выходного слоя) как LeNet Lab. Можно также изучить лучшую архитектуру для полностью связанных слоев, чтобы лучше решить проблему, но я не пытался этого сделать для этого проекта.
Прекращение работы с новыми изображениями
Изображения были выбраны случайным образом из Интернета. Они были масштабированы до 32x32. Размер и ориентация выбраны случайным образом. Первое изображение представляет собой нарисованный знак, а не из реальной сцены, однако функции четко показаны, поэтому ожидается, что хорошо обученная сеть все же сможет правильно предсказать свой класс. Третье изображение, хотя на первый взгляд похоже на те, что есть в базе, имеет другой масштаб. Окончательного изображения нет даже в базе данных, поэтому интересно посмотреть, что предсказывает сеть. Два других изображения похожи на те, что есть в базе данных.
Модель имеет точность 60% на 5 изображениях. Таким образом, он может предсказать правильный класс для трех изображений. Точность новых изображений довольно низкая по сравнению с проверочными (94%) и даже тестовыми (93%) наборами. Некоторые возможные причины этого выделены ниже.
Модель достигает верхней 1 ошибки 40%. Ошибка топ-5 также составляет 40%, так как при неправильном прогнозе правильный класс не входит в топ-5 вариантов.
Кроме того, модель кажется достаточно уверенной во всех прогнозах, даже если некоторые из них неверны. Однако при ближайшем рассмотрении вы можете понять, почему его обманули для изображений 3 и 5. Размер изображения 3 отличается от размера знаков скорости в базе данных. Контур знака достигает границы изображения, тогда как на обучающих изображениях имеется достаточный фон. На изображении 5 круговые знаки в базе данных имеют форму круга, тогда как это треугольник. На сеть сильно влияет форма. Кроме того, стрелки на изображении также сильно поворачиваются влево, поэтому он выбран.
Заключительные замечания
Благодаря этому проекту я смог сначала привыкнуть к TensorFlow, а также разработать и настроить модель глубокого обучения для классификации дорожных знаков и добиться приемлемой точности. Есть много способов улучшить производительность. Во-первых, предоставляя сети больше выборок посредством увеличения данных. Во-вторых, пробуя более глубокие модели с более изящным уменьшением разрешения изображения. В-третьих, применяя больше методов предварительной обработки, таких как отбеливание данных и нормализация яркости изображения. Вы можете найти репозиторий github для моего проекта ниже. Кроме того, для целей этого проекта я также создал краткое руководство по TensorFlow, которое вы можете увидеть ниже.
Ресурсы
[1] Проект классификатора дорожных знаков на GitHub
Ссылки
[1] П. Семанет, Ю. ЛеКун, «Распознавание дорожных знаков с помощью многомасштабных сверточных сетей»