Обзор

  • Введение
  • Что такое DaiLE?
  • Вызовы
  • Что дальше?
  • Заключительные мысли
  • Обо мне

Введение

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

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

Вот моя попытка пройти через пробел: DaiLE.

Что такое DaiLE?

Проще говоря, DaiLE (названный в честь Дейла Эрнхардта) - это модель PyTorch, которая может воспроизводить гоночный симулятор Assetto Corsa (AC) с помощью входов контроллера. Он смотрит на последние 60 кадров игрового процесса, анализируя изображения на экране и соответствующие данные телеметрии, и решает, повернуть, ускориться или тормозить. Хотя он обучен только нескольким часам моих собственных данных о вождении, он часто по-новому реагирует на ситуации, которые видел раньше. Чтобы продемонстрировать это, вы можете увидеть, как он пробует мой любимый трек Mario Kart, Baby Park.

Менее упрощенная версия заключается в том, что DaiLE представляет собой сверточную рекуррентную нейронную сеть (CRNN), в которой ResNet18 используется в качестве кодировщика изображений, двухуровневый LSTM, который обрабатывает закодированные изображения и данные телеметрии, и выходной уровень, который решает, какие входы контроллера следует использовать. на следующем кадре. Затем DaiLE отправляет эти входные данные в vJoy, используя привязки pyvjoy для Python, которые проходят через настройки контроллера Big Picture Steam и в AC.

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

  1. play_to General.py: процедура сбора данных, которая позволяет передавать управление автомобилем между DaiLE и человеком-игроком (по мотивам MariFlow Сетблинга).
  2. record_data.py: (необязательно асинхронная) система сбора данных (DAQ), которая позволяет настраивать частоту дискретизации. Синхронный сбор данных не позволял DaiLE делать выводы во время процедуры play_toght, что приводило к гораздо более низкой производительности. Захват данных неблокирующим способом кажется прямым улучшением во многих отношениях.

DaiLE на данный момент обучается исключительно под присмотром; ему показывают случайные партии из 60-кадровых последовательностей (с интервалом 1/15 секунды) и просят предсказать, какие входные данные следует использовать для 60-го кадра. Соответственно, он проявляет признаки интеллекта только на следах, которые он видел во время своего обучения. Кто-то может возразить, что это означает, что DaiLE просто переоснащен треками, которые он видел раньше, но я думаю, что это не так, поскольку вероятностное пространство на треке довольно велико, и он демонстрирует новое поведение даже в ситуациях, очень похожих на те. с которой он должен быть знаком.

После того, как DaiLE обучен, самое время проверить его на ходу. Я создал класс DaiLE, который позволяет создавать экземпляры конкретной версии модели (на случай, если вы обучили несколько разных моделей) и делает безболезненным вывод в реальном времени в реальном времени. Среда выполнения вывода использует окно OpenCV для постоянного отображения вводимых пользователем данных DaiLE.

Вызовы

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

Сложно сформулировать проблему.

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

Сбор данных в реальном времени - сложная задача.

Я обнаружил, что создание согласованного потока данных довольно сложно при наличии ресурсоемкого моделирования, такого как Assetto Corsa. Моя первоначальная методика выборки данных работала безупречно при тестировании в вакууме - она ​​снимала скриншоты и ввод с моего контроллера без каких-либо задержек или ошибок, когда игра не была запущена, - но она полностью развалилась, когда пришло время фактически получить данные для этого проекта. Вводы контроллеров были особенно неприятными, так как быстрый обзор данных после пробного запуска показал, что записанные входы контроллера не отражали мои истинные вводы.

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

Обучение работе с видео отнимает много времени.

Как известно, тренировка с видеоданными обходится дорого. Носитель богат данными, громоздок для предварительной обработки (по сравнению с табличными данными) и очень быстро занимает память. Вдобавок создание PyTorch DataLoader для этого формата сложнее, чем для табличных данных, с которыми я обычно работаю. Я быстро почувствовал влияние всего этого: по мере того, как мой набор данных увеличивался в размерах, время обучения увеличивалось вместе с ним. Я работал над максимальной оптимизацией этого процесса, но был вынужден начать тренировку DaiLE за ночь. У меня есть идеи, как сделать обучение более эффективным, чем сейчас, но я еще не успел их реализовать.

Вывод в реальном времени требует больших усилий.

Мой компьютер должен был запускать Assetto Corsa и DaiLE одновременно с высокой частотой кадров. Поскольку DaiLE обучался на данных, захваченных со скоростью 15 кадров в секунду, любое существенное падение частоты кадров ниже этой приводит к неустойчивому поведению. В то же время, однако, я обнаружил, что обучение DaiLE на данных, полученных с частотой менее 15 кадров в секунду, приводит к нестабильному поведению независимо от частоты кадров Assetto Corsa во время вывода.

Что дальше?

Контролируемый DaiLE

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

Неконтролируемый DaiLE

Однако, исчерпав свои идеи на этой итерации проекта, я хочу перейти к подходу к обучению с подкреплением. Я добился невероятного успеха с Sethbling’s MarIQ и Yosh’s Trackmania AI. Я знаю, что этот этап потребует еще более тяжелых вычислений, чем контролируемый DaiLE, но я надеюсь получить доступ к лучшим обучающим ресурсам к тому времени, когда я буду готов перейти на следующий уровень!

Заключительные мысли

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

Спасибо, что нашли время прочитать эту статью! Если у вас есть вопросы по этому проекту, напишите сообщение в комментариях или свяжитесь со мной в LinkedIn. Вы можете найти свободно распространяемый и изменяемый код моей работы здесь, в моем репозитории DaiLE GitHub.

Обо мне

Полтора года назад, после долгой стажировки в Honda, я решил полностью переключить свою карьеру с проектирования машиностроения на машинное обучение. Я всегда был увлечен информатикой, несмотря на то, что не изучал ее формально, и занимаюсь программированием в течение многих лет, так что переход был скорее сменой фокуса, чем полной сменой парадигмы. Тем не менее, мне нужно было посвятить серьезное время самообучению машинному обучению. Я потратил много выходных и вечеров на курсы по Udacity и Udemy, от компьютерного зрения до веб-дизайна (поскольку многие продукты машинного обучения основаны на веб-технологиях), что привело меня к моей первой стажировке в качестве исследователя машинного обучения в местной больнице.

С тех пор я получил степень магистра, отправил свою первую статью для публикации и теперь официально прохожу курсы информатики в Университете штата Огайо. И теперь, с DaiLE, я создал свой первый общедоступный проект машинного обучения с нуля (т. Е. Без готовых набросков проекта или руководств для рук).