1. Введение:

В этом проекте я создал классификатор распознавания дорожных знаков с использованием сверточной нейронной сети и тензорного потока. Кроме того, я точно настроил гиперпараметры, чтобы достичь точности не менее 93% в Наборе данных о дорожных знаках Германии.

  • Найдите исходный код со ссылкой на Github: Traffic_Sign_Classifier.ipynb
  • Доступна html-версия: Traffic_Sign_Classifier.html
    Примечание: размер html-файла составляет 1,9 МБ, поэтому Github не может его отобразить. Загрузите и откройте его с помощью Chrome или IE в вашем регионе.

2. Сводка и исследование набора данных

На этом этапе я изучил и проанализировал набор данных, чтобы лучше манипулировать им в этом проекте. Я сделал четыре шага, чтобы рассчитать сводку дорожного знака в этом наборе данных:

  • Основное резюме

Я использую numpy и pandas для вычисления базовой статистической информации, такой как количество обучающих выборок, количество тестовых выборок, форма изображения (т. е. np.shape(image)) и уникальные метки (т. е. np.unique). Результат:

Number of training examples = 34799
Number of testing examples = 12630
Image data shape = (32, 32, 3)
Number of classes = 43

Обратите внимание, что фигура изображения имеет 3 измерения: каждое изображение имеет ширину = 32 пикселя, высоту = 32 пикселя и 3 цветовых канала (т. е. красный, зеленый, синий).

  • Исследовательская визуализация

Всего в наборе данных 43 различных типа дорожных знаков. Я построил по одному образцу изображения для каждой категории, как показано ниже. Обратите внимание, что заголовок представляет собой «название категории дорожных знаков» в качестве ссылки.

Наблюдение: некоторые изображения повернуты, размыты, искажены или темнее других. Например, изображение «Скользкая дорога» в 6-м ряду от самого правого столбца еще труднее распознать человеку! Эти факторы действительно влияют на точность распознавания в дальнейшем и требуют дополнительной работы для тщательного рассмотрения.

  • Распространение

Я начертил распределение изображений для этих образцов дорожных знаков, чтобы показать, сколько изображений для каждой категории. Распределение для обучающей выборки следующее:
X: индекс категории дорожных знаков
Y: количество образцов изображения в этой категории

Я также построил распределение набора проверки следующим образом:

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

  • Подсчитать общее количество изображений в каждой категории

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

3. Проектирование и тестирование архитектуры модели

Предварительно обработайте данные изображения

  1. Оттенки серого. В качестве первого шага я использую прямое вычисление для преобразования изображения RGB с 3 каналами в изображение в градациях серого с одним единственным каналом.

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

  • небольшое использование памяти: для каждого пикселя RGB имеет 3 канала, и каждому каналу требуется 8-битное хранилище, в то время как оттенки серого используют 8-бит только для одного канала.
  • цветовая инвариантность: классификатор дорожных знаков не зависит от цвета, что означает, что ему нужно только обнаруживать края внутри изображения, а информация о цвете не помогает.
  • сложность визуализации: оттенками серого легче манипулировать и визуализировать, поскольку они имеют два пространственных измерения и одно измерение яркости. Напротив, RGB имеет два пространственных измерения и три цветовых измерения.
  • скорость обработки: изображение в градациях серого содержит меньше данных, что ускоряет его обработку. В частности, это может сэкономить огромное количество времени при обработке видео, если вы представляете видео как длинную последовательность изображений.

2. Масштабирование или нормализация: вторым шагом является масштабирование или нормализация каждого изображения. Этот шаг изменяет диапазон интенсивности пикселей, чтобы все изображения могли иметь одинаковый диапазон значений пикселей.

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

Причина нормализации следующая:

  • растяжение контраста:изображения могут иметь очень разный контраст из-за бликов, изменения интенсивности освещения и т. д. Это делает изображения либо очень яркими, либо слишком темными, что трудно распознать.
  • Стабильность модели: искаженные значения пикселей вредны, поскольку наша модель будет умножать веса и добавлять смещения к этим пикселям изображения. Если задействованы чрезвычайно большие или малые значения, обе операции могут усилить асимметрию и вызвать большую ошибку.
  • улучшить расчет градиента: модель должна рассчитывать градиенты при обратном распространении. С перекошенными значениями пикселей вычисление градиента может выйти из-под контроля, что является кошмаром…

3. Интенсивность масштабирования. В качестве эксперимента я обнаружил, что простое линейное преобразование можно дополнительно улучшить с помощью метода «exposure.rescale_intensity» из библиотеки skimage. Он равномерно масштабировал интенсивность изображения, чтобы значения пикселей находились в согласованном диапазоне, и достигал лучших результатов.

Вот общий поток нашей предварительной обработки.

Архитектура модели

Я использую аналогичную модель LeNet, представленную в курсе. Он включает в себя два сверточных слоя и три полносвязных слоя. Общая архитектура показана ниже. Фигура обозначает размер вывода этого слоя. Мы используем Relu в качестве функции активации.

Примечание:
(1) после каждого сверточного слоя есть relu и max_pool.
(2) существует только связь между полносвязными слоями.
(3) НЕТ операции после линейного преобразования в последнем выходном слое.
(4) max_pooling каждый раз будет уменьшать размер изображения вдвое, потому что:
- мы используем окна 2x2 (размер ядра = [1, 2, 2, 1])
- перемещаем 2 пикселя в пространственном направление каждый раз (шаги = [1, 2, 2, 1]).

размер ядра = [размер_пакета, высота, ширина, канал]
размер шага = [размер_пакета, высота, ширина, канал]

Обучение модели

Во время обучения этой модели я использую следующие гиперпараметры:

скорость обучения = 0,001
EPOCHS = 50
BATCH_SIZE = 256

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

  • определить оптимизатор: мы используем «оптимизатор Адама», чтобы минимизировать функцию потерь, используя скорость обучения = 0,001. Вместо классического алгоритма стохастического градиентного спуска (SGD) мы используем здесь метод Адама для повышения производительности, поскольку метод Адама итеративно обновляет веса на основе обучающих данных.

  • Обучение модели: весь набор данных разделен на несколько пакетов, и каждый пакет содержит 256 изображений. Код фреймворка показан ниже.
    (1) В каждую эпоху мы перемешивали все обучающие изображения, чтобы изображения в каждом пакете могли лучше представлять весь набор обучающих данных.
    (2) оптимизатор работает над пакеты обучающих изображений для минимизации функции потерь (используйте функцию «training_operation») для обновления весов и смещения в нашей модели.
    (3) После того, как оптимизатор будет выполнен для всех данных обучения, мы применяем модель к набору данных проверки и оцениваем производительность нашей модели.
    (4) Процесс продолжается до итерации следующей эпохи, пока мы не достигнем ›93% точности проверки.

Подход к поиску решения

Мои окончательные результаты модели были:

Validation Accuracy = 0.95
Test Accuracy = 0.933

Я выбрал известную архитектуру, созданную Яном Лекуном в 1998 году. Эта исходная модель включает в себя два сверточных слоя и полносвязный слой, как показано ниже.

Он отлично справляется с распознаванием изображений, в частности, с рукописными числами (например, распознавание цифр MNIST).

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

Первоначальный результат плохой с архитектурой LeNet:

EPOCH 1 … точность проверки = 0,054
EPOCH 2 … точность проверки = 0,048
EPOCH 3 … точность проверки = 0,048
EPOCH 4 … точность проверки = 0,048
EPOCH 5 … точность проверки = 0,054

Я сделал несколько настроек гиперпараметров для повышения точности. Но самые важные гиперпараметры — это скорость обучения, эпоха и глубина сверточных слоев!

Здесь я показываю некоторые настройки в качестве примера:

  • Добавить отсев в полносвязном слое → все еще не очень хорошо
EPOCH 1 ...Validation Accuracy = 0.048
EPOCH 2 ...Validation Accuracy = 0.048
EPOCH 3 ...Validation Accuracy = 0.054
EPOCH 4 ...Validation Accuracy = 0.054
EPOCH 5 ...Validation Accuracy = 0.054
  • Уменьшите скорость обучения с 0,1 до 0,001 → большое улучшение!
EPOCH 1 ...Validation Accuracy = 0.433 loss = 1.822
EPOCH 2 ...Validation Accuracy = 0.676 loss = 0.929
EPOCH 3 ...Validation Accuracy = 0.765 loss = 0.690
EPOCH 4 ...Validation Accuracy = 0.792 loss = 0.405
EPOCH 5 ...Validation Accuracy = 0.835 loss = 0.536
  • Снижайте скорость обучения с 0,001 до 0,0001 → становится хуже!
EPOCH 1 ...Validation Accuracy = 0.065 loss = 3.528
EPOCH 2 ...Validation Accuracy = 0.097 loss = 3.338
EPOCH 3 ...Validation Accuracy = 0.170 loss = 3.002
EPOCH 4 ...Validation Accuracy = 0.263 loss = 2.683
EPOCH 5 ...Validation Accuracy = 0.329 loss = 2.320
  • Увеличьте количество эпох с 5 до 10 → намного лучше!
EPOCH 1 ...Validation Accuracy = 0.362 loss = 2.073
EPOCH 2 ...Validation Accuracy = 0.638 loss = 1.035
EPOCH 3 ...Validation Accuracy = 0.731 loss = 0.705
EPOCH 4 ...Validation Accuracy = 0.794 loss = 0.564
EPOCH 5 ...Validation Accuracy = 0.818 loss = 0.513
EPOCH 6 ...Validation Accuracy = 0.823 loss = 0.267
EPOCH 7 ...Validation Accuracy = 0.839 loss = 0.247
EPOCH 8 ...Validation Accuracy = 0.857 loss = 0.312
EPOCH 9 ...Validation Accuracy = 0.860 loss = 0.326
EPOCH 10 ...Validation Accuracy = 0.868 loss = 0.208
  • Исследование перетасовки в каждую эпоху → незначительное влияние на проверку
  • Измените значение «сигма» для начальных значений веса → 0,1 лучше!
  • Используйте другую функцию активации (например, программный знак) → без больших последствий
  • Используйте «rescale_intensity» для повышения контрастности → большое улучшение!
EPOCH 1 ...Validation Accuracy = 0.573 loss = 1.256
EPOCH 2 ...Validation Accuracy = 0.735 loss = 0.732
EPOCH 3 ...Validation Accuracy = 0.798 loss = 0.480
EPOCH 4 ...Validation Accuracy = 0.832 loss = 0.400
EPOCH 5 ...Validation Accuracy = 0.850 loss = 0.360
  • … (много других работ по настройке)
  • Наконец, увеличьте глубину сверточных слоев → большое улучшение!

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

сверточный слой 1: глубина изменена с 8 до 16
сверточный слой 2: глубина изменена с 16 до 32

Затем точность проверки можно повысить до 0,948!

Можем ли мы сделать лучше? Я пробовал следующее:

глубина сверточного слоя 1 = 64
глубина сверточного слоя 2=128

Я чувствую, что вычисления стали медленнее, чем раньше, но точность можно повысить до более 96% всего за 20 эпох!

Training...

EPOCH 1 ... validation accuracy = 0.855 loss = 0.255
EPOCH 2 ... validation accuracy = 0.896 loss = 0.156
EPOCH 3 ... validation accuracy = 0.922 loss = 0.073
EPOCH 4 ... validation accuracy = 0.916 loss = 0.036
EPOCH 5 ... validation accuracy = 0.928 loss = 0.023
EPOCH 6 ... validation accuracy = 0.919 loss = 0.015
EPOCH 7 ... validation accuracy = 0.924 loss = 0.020
EPOCH 8 ... validation accuracy = 0.926 loss = 0.003
EPOCH 9 ... validation accuracy = 0.930 loss = 0.002
EPOCH 10 ... validation accuracy = 0.930 loss = 0.006
EPOCH 11 ... validation accuracy = 0.939 loss = 0.004
EPOCH 12 ... validation accuracy = 0.931 loss = 0.018
EPOCH 13 ... validation accuracy = 0.942 loss = 0.014
EPOCH 14 ... validation accuracy = 0.926 loss = 0.003
EPOCH 15 ... validation accuracy = 0.938 loss = 0.004
EPOCH 16 ... validation accuracy = 0.938 loss = 0.010
EPOCH 17 ... validation accuracy = 0.958 loss = 0.003
EPOCH 18 ... validation accuracy = 0.959 loss = 0.010
EPOCH 19 ... validation accuracy = 0.959 loss = 0.000
EPOCH 20 ... validation accuracy = 0.961 loss = 0.000
EPOCH 21 ... validation accuracy = 0.960 loss = 0.000
EPOCH 22 ... validation accuracy = 0.960 loss = 0.000
EPOCH 23 ... validation accuracy = 0.960 loss = 0.000
EPOCH 24 ... validation accuracy = 0.961 loss = 0.000

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

Точность теста составляет всего 80%! Знак стоп распознается неправильно.

Для борьбы с этим я уменьшил гиперпараметры глубины до следующих:

глубина сверточного слоя 1 = 64
глубина сверточного слоя 2 = 32

Таким образом, точность тестирования новых изображений повышается до 100 %!

4. Тестовая модель на новых изображениях

Новые изображения из Интернета

  • Я нашел пять изображений дорожных знаков Германии из поиска Google. Я фактически вырезаю их из больших изображений.
  1. первое изображение — знак «ухабистая дорога». Он имеет жалюзийные изменения на поверхности знака, что может привести к тому, что наша модель сделает неправильное определение.

2. второе изображение — знак «главная дорога». У него есть небо и облака в качестве фона. Это может быть трудно классифицировать, потому что часть знака белая и очень близка к фону. Таким образом, знак может легко смешать знак с облаком сзади вместе.

3. третье изображение – знак «автомобилям запрещено». В правом нижнем углу есть человек в красной куртке. Это очень близко к внешнему красному кругу знака. Это может привести к ошибке для нашего классификатора.

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

5. пятое изображение – знак «стоп». У него более темный фон, а края знака перемешаны с фоном силовой башни. Это может вызвать трудности с правильной классификацией знака остановки.

Результат проверки на новых изображениях

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

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

  • Каждая группа — это прогнозы для каждого изображения (ярлык выделен жирным шрифтом);
  • В каждой строке показана предполагаемая вероятность каждой категории из модели.
  • Категория с самой высокой вероятностью является результатом прогноза.

Например, для изображения «Ухабистая дорога» наша модель предсказала, что это изображение относится к категории «Ухабистая дорога» с вероятностью 99,8%. Поэтому модель считает этот образ знаком «Ухабистая дорога».

------------------------------------------------------------

	 True Label is: =    22:Bumpy road                    

   22: Bumpy road                     99.812%
   29: Bicycles crossing              0.101%
   24: Road narrows on the right      0.087%
   31: Wild animals crossing          0.000%
   26: Traffic signals                0.000%
------------------------------------------------------------
------------------------------------------------------------

	 True Label is: =    12:Priority road                 

   12: Priority road                  100.000%
   40: Roundabout mandatory           0.000%
   26: Traffic signals                0.000%
   38: Keep right                     0.000%
   42: End of no passing by vehicles over 3.5 metric tons 0.000%
------------------------------------------------------------
------------------------------------------------------------

	 True Label is: =    15:No vehicles                   

   15: No vehicles                    99.993%
    2: Speed limit (50km/h)           0.005%
    3: Speed limit (60km/h)           0.002%
    5: Speed limit (80km/h)           0.000%
    1: Speed limit (30km/h)           0.000%
------------------------------------------------------------
------------------------------------------------------------

	 True Label is: =    33:Turn right ahead              

   33: Turn right ahead               100.000%
    3: Speed limit (60km/h)           0.000%
   35: Ahead only                     0.000%
   39: Keep left                      0.000%
    1: Speed limit (30km/h)           0.000%
------------------------------------------------------------
------------------------------------------------------------

	 True Label is: =    14:Stop                          

   14: Stop                           100.000%
   17: No entry                       0.000%
   38: Keep right                     0.000%
   34: Turn left ahead                0.000%
   32: End of all speed and passing limits 0.000%
------------------------------------------------------------

5. Резюме и заключение

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

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

Наоборот, некоторые другие параметры или операции не помогают, например операция отсева и методы заполнения «ДЕЙСТВИТЕЛЬНО»/«ТАК ЖЕ». Может быть, я смогу попробовать их в будущем проекте и увидеть их влияние.

В целом, это отличный опыт обучения. Я узнал так много знаний за последние несколько недель. Спасибо за организацию занятий и подготовку материала!

Счастливого дня благодарения! :-)✌️

Оригинал: 26 ноября 2017 г., 15:03

Обновлено: 4 декабря 2017 г., 22:32.