Для проекта Udacity Self Driving Car Nanodegree Project 3 они создали симулятор вождения, который можно было использовать для обучения и тестирования моделей автономного рулевого управления. Я обучил и сравнил две модели сверточной нейронной сети (CNN) с сильно различающейся архитектурой, используя изображения, направленные вперед, и углы поворота от транспортного средства в симуляторе. Результаты показывают, что выбор архитектуры CNN для этого типа задач менее важен, чем используемые данные и методы дополнения. В результатах можно увидеть параллельные видеоролики моделей в симуляторе.

Подход

Мой общий подход к этому проекту состоял в том, чтобы использовать предоставленные обучающие данные из Udacity и столько методов увеличения данных, сколько необходимо для создания моделей, которые могли бы успешно перемещаться по различным трекам в симуляторе. Я попробовал две разные модели CNN: первая из них - хорошо зарекомендовавшая себя модель NVIDIA из их статьи:

Https://images.nvidia.com/content/tegra/automotive/images/2016/solutions/pdf/end-to-end-dl-using-px.pdf

а вторая модель аналогична той, которую я разработал для проекта Udacity с открытым исходным кодом №2 «Использование глубокого обучения для прогнозирования углов поворота»:

Https://github.com/chrisgundling/self-driving-car/tree/master/steering-models/community-models/cg23

Модели сильно различались, поскольку NVIDIA использует только около 250 000 параметров, тогда как исходная модель в стиле VGG, которую я пробовал, имела почти 34 миллиона параметров.

Я экспериментировал с различными методами предварительной обработки данных, 7 различными методами увеличения данных и варьировал отсев для каждой из двух моделей, которые я тестировал. В конце концов, я обнаружил, что, хотя модель в стиле VGG ведет себя немного плавнее, для этого потребовалось больше настройки гиперпараметров. Архитектура NVIDIA лучше справилась с обобщением на тестовый трек (Track2) с меньшими усилиями. Последняя модель NVIDIA не использовала дропаут и могла двигаться как по дорожке 1, так и по 2. Я столкнулся с проблемами задержки рулевого управления с большей моделью в стиле VGG во время тестирования в симуляторе на ЦП. В итоге я уменьшил размер изображения на этой модели с 128X128X3 до 64X64X3 и вдвое уменьшил размер полностью подключенного слоя. Это позволило модели в стиле VGG ездить как по треку 1, так и по треку 2.

Благодарности

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

Https://chatbotslife.com/using-augmentation-to-mimic-human-driving-496b569760a9#.yget03t5g

Я также хотел бы поблагодарить Юсуфа Фаузана из Udacity за его реализацию вращательных преобразований перспективы. Я встретил Юсуфа на мероприятии «Outside the Lines», и он применил эту технику для Udacity’s Challenge # 2. Сценарий использует матрицу поворота для преобразования перспективы в различной степени изображения.

Исследование данных

Данные, предоставленные Udacity, состояли из 8036 центральных, левых и правых изображений в формате .jpg с общим объемом данных 24109 примеров (всего 323 МБ данных!). Все эти обучающие изображения были взяты из дорожки 1. Изображения имели ширину 320 на 160 высоту. Ниже показан пример левого / центрального / правого изображений, снятых с одного временного шага от автомобиля.

Углы поворота, представленные в журнале вождения набора данных Udacity, показаны ниже. Углы поворота были предварительно масштабированы с коэффициентом 1/25, так что они находятся в диапазоне от -1 до 1 (максимальный / минимальный угол поворота, создаваемый симулятором, составляет +/- 25 градусов).

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

Предварительная обработка данных

Я внимательно следил за обсуждениями в Slack сбора данных для обучения. Казалось, что многие люди испытывают трудности со сбором данных о «плавном» рулевом управлении, используя только клавиатуру своего компьютера. Данные Udacity помогли решить эту проблему, но, основываясь на опыте использования реальных данных рулевого управления от Udacity's Challenge # 2, предоставленные данные симулятора рулевого управления по-прежнему выглядели гораздо более ступенчатыми.

Экспоненциальное сглаживание

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

Нормализация

Я нормализовал все значения пикселей изображения, используя уравнение (x-128) / 128. Это нормализует значения между -1 и 1. Я сделал это для данных обучения, данных проверки и реализовал в сценарии вождения симулятора для тестирования модели.

Обрезка

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

Изменение размера

Для модели NVIDIA я придерживался их подхода и использовал изображения высотой 66 и шириной 200 пикселей. Для модели стиля VGG я использовал изображения с высотой 64 на 64 ширины, чтобы уменьшить исходную модель из Задачи № 2 от Udacity.

Увеличение объема данных

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

Другим важным преимуществом аугментаций является то, что они имитируют восстановление. Преобразование точек обзора, смещение изображений и использование изображений влево / вправо - все это добавляет обучающие данные, которые имитируют возвращение автомобиля к центру без необходимости собирать какие-либо данные для восстановления. Аугментации выполнялись «на лету» с использованием специального метода генератора / урожая. Были реализованы следующие методы увеличения данных:

  1. Преобразования перспективы / точки обзора - аналогично тому, что описано в документе NVIDIA, к изображениям применялись преобразования перспективы вращения. Мне пришлось немного настроить регулировку угла поворота для перспективных преобразований, поскольку я обнаружил, что угол однозначного преобразования перспективы для регулировки угла поворота был слишком большим. Я остановился на равномерном повороте перспективы изображения от -80 до 80 градусов. Затем я разделил перспективный угол на 200, чтобы отрегулировать угол поворота. Это дало возможность регулировки максимального / минимального угла поворота рулевого колеса на +/- 0,4 единицы или 10 градусов.
  2. Переворачивание изображения. Поскольку левые и правые повороты в обучающих данных неодинаковы, переворачивание изображения было важно для обобщения модели на трек 2. Я также перевернул знак поворота. угол, когда изображение было перевернуто.
  3. Изображения левой / правой камеры. Я использовал изображения левой / правой камеры автомобиля, что сразу утроило размер обучающих данных. После тщательного изучения левого и правого изображений и поиска общих черт с центральными изображениями я подсчитал, что левые и правые изображения смещены по горизонтали от центральной камеры примерно на 60 пикселей. Основываясь на этой информации, я выбрал коррекцию угла поворота +/- 0,25 единицы или +/- 6,25 градуса для этих левых / правых изображений.
  4. Горизонтальное / вертикальное смещение - я применил к изображениям горизонтальный и вертикальный сдвиг. Мои максимальные / минимальные горизонтальные и вертикальные смещения составляли 40 пикселей в каждом направлении. Я настроил это значение во время обучения модели. Учитывая, что я оценил смещение левого / правого изображения на 60 пикселей, я применил немного меньшую коррекцию угла поворота для максимального горизонтального смещения. Вертикальные смещения не корректировались по углу поворота.
  5. Яркость изображения. Я скорректировал яркость изображений, преобразовав в цветовое пространство HSV и масштабируя значения V пикселей от 0,5 до 1,1. Это было в основном для того, чтобы помочь обобщить дорожку 2, где изображения в целом были темнее.
  6. Размытие изображения. Я не уверен, насколько полезен этот метод для симулятора, но он должен помочь модели обобщить при использовании большего количества данных типа «реального мира», которые временами страдают от нечеткости. Я использовал переменное сглаживание по Гауссу, чтобы размыть изображения.
  7. Поворот изображения - В отличие от перспективных преобразований, я реализовал небольшие повороты изображений, чтобы имитировать дрожание камеры. Еще раз не уверен, насколько это было полезно для симулятора, но было бы полезно для реальной камеры на беспилотном автомобиле.

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

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

Генератор данных

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

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

  • ang: метка угла поворота для изображения
  • cam: выбор камеры (левая / центральная / правая)
  • aug: 1 - нет аугментации, 2 - да аугментации
  • opt: Параметр увеличения данных: 1. Переворот, Джиттер, Размытие, Яркость, 2. Сдвиг изображения и 3. Преобразование поворотной точки обзора

Настройка модели и гиперпараметры

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

  • Максимальное количество эпох - 8 (5 или 6 эпох обучения обычно давали лучшую модель для NVIDIA и только 1–3 эпохи для стиля VGG)
  • Образцов на эпоху - 23040
  • Размер партии - 64
  • Оптимизатор - Адам со скоростью обучения 1e-4
  • Активации - Relu для стиля VGG и Elu для модели NVIDIA

Модель NVIDIA, реализованная в Keras, показана ниже:

# Layer 1
x = Convolution2D(24, 5, 5, activation=’elu’, subsample=(2, 2), border_mode=’valid’, init=’he_normal’)(img_input)
# Layer 2
x = Convolution2D(36, 5, 5, activation=’elu’, subsample=(2, 2), border_mode=’valid’, init=’he_normal’)(x)
# Layer 3
x = Convolution2D(48, 5, 5, activation=’elu’, subsample=(2, 2), border_mode=’valid’, init=’he_normal’)(x)
# Layer 4
x = Convolution2D(64, 3, 3, activation=’elu’, subsample=(1, 1), border_mode=’valid’, init=’he_normal’)(x)
# Layer 5
x = Convolution2D(64, 3, 3, activation=’elu’, subsample=(1, 1), border_mode=’valid’, init=’he_normal’)(x)
# Flatten
y = Flatten()(x)
# FC 1
y = Dense(100, activation=’elu’, init=’he_normal’)(y)
# FC 2
y = Dense(50, activation=’elu’, init=’he_normal’)(y)
# FC 3
y = Dense(10, activation=’elu’, init=’he_normal’)(y)
# Output Layer
y = Dense(1, init=’he_normal’)(y)
model = Model(input=img_input, output=y)
model.compile(optimizer=Adam(lr=1e-4), loss = ‘mse’)

Модельная архитектура

Архитектуры моделей для каждой из двух моделей можно увидеть ниже. Как упоминалось во введении, основным параметром настройки этих моделей было исключение. Для модели NVIDIA было несколько неожиданно обнаружить, что модель показала лучшие результаты как на дорожке 1, так и на дорожке 2, без каких-либо потерь. Любой отсев приводил к тому, что автомобиль не слишком круто поворачивал в поворотах. Для модели типа VGG некоторые выпадения в последнем сверточном слое и полностью подключенном слое улучшили производительность.

Структура и параметры модели типов NVIDIA

Это дает 0,6 МБ для каждого изображения при прямом проходе и 1,2 МБ при обратном проходе. При размере пакета 64 максимальное использование памяти будет 75 МБ во время обратного прохода.

Структура и параметры модели типа VGG

Это дает 1,2 МБ (~ 0,3 МБ * 4 байта) для каждого изображения при прямом проходе и 2,4 МБ на обратном проходе. При размере пакета 64 максимальное использование памяти будет 150 МБ во время обратного прохода. Если сравнивать структуру и параметры с моделью NVIDIA, то при почти 4,3 миллионах параметров эта модель имеет значительно больше параметров, чем NVIDIA.

Результаты

Следующие видео показывают параллельное сравнение двух моделей для трека 1 и 2. Хотя модель в стиле VGG кажется немного более плавной, модель NVIDIA лучше обобщена для трека 2. У меня возникли проблемы с чрезмерной подгонкой к Трек 1 с использованием модели стиля VGG, и поведение при вождении сильно зависело от выбывания и количества эпох, в которые модель была обучена.

Движение по маршруту 1 с величиной дроссельной заслонки 0,2

Движение по маршруту 2 с величиной дроссельной заслонки 0,3

Выводы

С тех пор, как Udacity впервые выпустил проекты Nanodegree Term 1, я с нетерпением ждал возможности поработать над этим. Учитывая трудности, связанные со сбором высококачественных и количественных реальных данных о дороге, возможность обучения этих моделей в симуляторе с, казалось бы, бесконечными данными может обеспечить значительный прорыв в области автономного вождения. Как видно из этого проекта, даже с относительно небольшим объемом данных и довольно простой моделью CNN, автомобиль смог успешно пройти оба курса.

Я с нетерпением жду продолжения этой работы и работаю над реализацией подходов RNN / LSTM и обучения с подкреплением для управления рулевым управлением, дроссельной заслонкой и тормозом. Мне также интересно использовать комбинации данных реального мира и данных симулятора для обучения этих моделей, чтобы понять, как модель, обученная на симуляторе, может быть обобщена на реальный мир или наоборот.

Оборудование / Настройка тестирования

Я обучил эти модели с помощью модифицированной версии Udacity CarND AWS AMI с графическим процессором g2.2xlarge и протестировал модели на своем ноутбуке Macbook Pro с процессором. Симулятор был настроен на «Самый быстрый» с разрешением экрана 640 X 480.

Код

Весь код этого проекта был реализован на Python, и его можно найти в моем профиле github здесь:

Https://github.com/chrisgundling