Используя машинное обучение для броска, легко попасть в корзину!

машинное обучение

Автор: Эйб Хаскинс (Twitter, Github)

В этой статье мы рассмотрим, как с помощью Unity3D и TensorFlow научить ИИ выполнять простую игровую задачу: забросить мяч в корзину. Полный исходный код доступен на Github. Если у вас есть какие-либо вопросы, пожалуйста, свяжитесь со мной в Twitter.

Примечание: ссылка на гитхаб

https://github.com/abehaskins/tf-jam

Введение в игру

В этой игре главная цель игрока – забросить мяч в корзину. На первый взгляд сделать это несложно, но когда кровь кипит, сердце бешено колотится, а публика восторженно аплодирует, попасть становится сложнее. Я говорю о классической игре в американский баскетбол? Нет, это не так. Я говорю о классической аркадной игре Midway NBA Jam.

Если вы играли в «NBA Jam» или в любую из игр, вдохновленных ею (включая настоящую лигу NBA, из которой, как я думаю, возникла лига), вы знаете, что навыки броска очень важны для игроков. в глаза. Все, что вам нужно сделать, это нажать и удерживать кнопку трансляции, а затем дождаться идеального момента, чтобы отпустить ее. ноВы когда-нибудь задумывались над тем, как это действие заклинания работает в игре? Какова дуга движения выбранного шара? Насколько сильна подача? Как компьютер определяет угол проекции?

Если вы сообразительны и хорошо разбираетесь в математике, возможно, вы сможете найти ответы на эти вопросы с помощью ручки и бумаги, но автор этого сообщения в блоге провалил экзамен по алгебре в 8-м классе, не говоря уже о том, чтобы рассчитать ответы, подобные этим: умные люди». Значит, мне нужно найти другой путь.

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

Начиная

Перед началом проекта нам необходимо подготовить следующие инструменты.

  • Unity: для моделирования баскетбола и создания физической среды.

  • Node.js и TensorFlow.js: для обучения модели

  • TensorFlowSharp: для встраивания моделей в Unity через пакет ресурсов агентов машинного обучения (ML-Agents).

  • tsjs-converter: используется для преобразования моделей TensorFlow.js в графики, которые можно использовать в Unity.

  • Google Таблицы: для простой визуализации нашего линейного регрессионного анализа.

Даже если вы не очень хорошо владеете какой-либо из вышеперечисленных техник, ничего страшного! (Я тоже не во всем разбираюсь!) Постараюсь объяснить, как эти инструменты работают вместе. Одним из недостатков использования такого количества методов является то, что я не могу охватить все детали в этой презентации, но я постараюсь предоставить ссылки на как можно больше внешних образовательных ресурсов!

Скачать проект

Я не собираюсь пересобирать проект шаг за шагом, поэтому предлагаю вам загрузить исходный код на Github и следовать моему темпу.

Примечание. Ссылка на исходный код на Github.

https://github.com/abehaskins/tf-jam

Уведомление:Вам необходимо загрузить и импортировать пакет ресурсов Unity для агентов машинного обучения (ML-Agents), чтобы использовать Tensorflow в C#. Если вы получаете такие ошибки, как Tensorflow не может быть найден в Unity, обязательно следуйте документации по установке Unity TensorflowSharp.

Примечание. Агенты машинного обучения (ML-Agents) ссылка Unity

https://github.com/Unity-Technologies/ml-agents

Ссылка на документацию по установке Unity TensorflowSharp

https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Using-TensorFlow-Sharp-in-Unity.md

Какова наша цель?

Для краткости ожидаемые результаты, которые мы установили для этого проекта, также просты. Мы хотим решить следующую задачу: если расстояние между котелком и корзиной равно X, то подать мяч с силой Y. Это так просто! Мы не пытаемся маркировать мяч или нацеливаться на какие-либо другие трюки, мы просто выясняем, насколько сильно ударить по мячу.

Если вам интересно узнать больше о том, как обучать более сложный ИИ в Unity, перейдите на Unity, чтобы получить более полные проекты агентов машинного обучения (ML-Agents). Методы, которые я описываю в этой статье, просты и легки, но не обязательно являются лучшими (потому что я все еще учусь!)

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

корзина и мяч

Как уже упоминалось ранее, наша главная цель — стрелять по мячу. Чтобы положить мяч в корзину, у нас сначала есть корзина и мяч. Вот где Unity пригодится.

Если вы новичок в Unity, просто знайте, что это игровой движок, который создает 2D- и 3D-игры для всех платформ. Unity имеет встроенный физический движок, базовые 3D-модели и отличную среду выполнения сценариев (Mono) для программирования игр на C#.

Я не художник, я просто перетащил блоки и собрал сцену стадиона.

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

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

Если вы посмотрите на метод OnTriggerEnter в /Assets/BallController.cs (каждый экземпляр баскетбольного мяча имеет этот скрипт), вы увидите, как эти два триггера можно использовать вместе.

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

стрелять

Пожалуйста, откройте /Assets/BallSpawnerController.cs. Это сценарий, зависящий от боулера, отвечающий за создание баскетбольного мяча и попытку попасть в кольцо. Вы также можете увидеть этот код в конце метода DoShoot().

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

Если вы еще не закрыли /Assets/BallController.cs, вы можете проверить наш метод Start(). Мы будем вызывать этот код при создании нового баскетбольного мяча.

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

Давайте попробуем запустить приведенный выше код, чтобы увидеть, как стреляет All-Star. Вы можете нажать кнопку ▶️ («Воспроизвести») в редакторе Unity, и вы увидите…

Наш игрок (назовем его «Красненький») почти каждый раз промахивается.

Почему Сяохун так плохо себя чувствует? Ответ кроется в строке кода в Assets/BallController.cs, в которой указано float force = 0.2f. Эта строка кода делает смелое утверждение, что все кадры должны быть абсолютно одинаковыми. Как видите, Unity строго «точно такой же». Повторяйте действие снова и снова с одной и той же силой, и один и тот же объект всегда отскакивает точно таким же образом. Все действия однообразны.

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

Случайные снимки, сбор данных

Мы можем просто изменить скорость на случайный размер, чтобы ввести случайный шум.

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

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

В то же время мы не хотим иметь возможность делать подачу только с одной позиции. Мы надеемся, что Сяохун сможет успешно стрелять с любого расстояния (если ему повезет). Найдите следующую строку в Assets/BallSpawnController.cs и раскомментируйте MoveToRandomDistance().

После повторного запуска мы увидим, как Сяохун взволнованно прыгает по корту после каждого удара.

Сочетание случайного движения со случайной силой дает нечто действительно замечательное: данные. Если вы посмотрите на консоль в Unity в этот момент, вы увидите, что каждый успешный выстрел регистрируется.

После каждого броска система записывает количество забитых голов, расстояние от места броска до кольца и усилие, необходимое для броска. Но этот прогресс слишком медленный, нам нужно ускориться. Вернитесь туда, где вы ранее добавили вызов MoveToRandomDistance(), и измените 0,3f (задержка 300 мс на выстрел) на 0,05f (задержка 50 мс).

Стреляйте еще раз, и мы увидим огромное увеличение количества голов.

Этот метод обучения работает отлично! Как видно по счетчику сзади: процент голов достиг около 6,4%. Но Сяохун все еще не так хорош, как Стефен Карри. Говоря о тренировках, действительно ли мы чему-то научились? Как работает TensorFlow? Где веселье? Это зависит от следующего шага. Теперь мы готовы извлечь приведенные выше данные из Unity и построить модель для прогнозирования желаемой силы.

Прогнозирование, моделирование и регрессия

Просмотр данных в Google Sheets

Прежде чем погрузиться в TensorFlow, я хотел посмотреть данные, поэтому оставил Unity включенным до тех пор, пока Сяохуну не удалось сделать около 50 снимков. Если вы посмотрите в корень вашего проекта Unity, вы должны увидеть новый файл success_shots.csv. Вот необработанный файл дампа, созданный в Unity для каждой успешной цели! Я экспортировал этот файл из Unity для удобного анализа в электронной таблице.

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

Вау! Проверьте это. Я имею в виду, посмотрите на эту картинку. Я хочу сказать, что это потрясающе... ну, должен признать, я не очень понял эту картину, когда только начинал. Давайте подробно проанализируем эту диаграмму.Ось Y представляет силу проекции, а ось X представляет расстояние проекции.Эти точки координат распределены между двумя осями. График показывает очень сильную корреляцию между требуемой силой и расстоянием проекции (хотя есть некоторые случайные выбросы, которые сильно отличаются).

На самом деле, вы также можете прочитать это так: «TensorFlow очень хорош в этом».

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

Создайте модель TensorFlow.js

Откройте файл tsjs/index.js в вашем любимом редакторе. Этот файл является просто скриптом и не имеет ничего общего с Unity. Мы можем использовать этот скрипт для обучения модели на основе данных в файле success_shots.csv.

Полный метод обучения и сохранения модели описан ниже...

Как видите, в эксплуатации нет ничего сложного. Мы загружаем данные из файла .csv и создаем ряд точек координат X и Y, что очень похоже на операцию Google Sheets выше! Здесь мы просим модель «подогнать» эти данные. Сохраните модель, когда закончите, и используйте ее позже!

К сожалению, TensorFlowSharp не поддерживает форматы моделей, которые может сохранить Tensorflow.js. Для этого нам нужно сделать несколько умных преобразований, чтобы модель можно было встроить в Unity. Я использовал некоторые утилиты, чтобы помочь с этим. Общий процесс выглядит следующим образом: преобразуйте модель из формата TensorFlow.js в формат Keras, создайте контрольную точку в этом формате и объедините контрольную точку с определением Protobuf Graph, чтобы получить определение Frozen Graph, которое затем можно встроить. Единство.

К счастью, если вы хотите быстро приступить к работе, вы также можете пропустить эти шаги и просто запустить tsjs/build.sh; если все пойдет хорошо, он автоматизирует все шаги и заполнит замороженную модель в Unity.

Внутри Unity мы можем видеть, как модель взаимодействует с GetForceFromTensorFlow() в Assets/BallSpawnController.cs.

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

При использовании model.predict в TensorFlow.js он автоматически передает ваши входные данные в правильный входной узел графа и дает вам выходные данные этого узла после завершения вычислений. Однако TensorFlowSharp работает по-другому, требуя от нас взаимодействия с узлами графа напрямую по имени.

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

День игры!

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

Мы видим примерно 10-кратное увеличение количества голов! Что, если мы будем тренировать Сяохуна часами и собирать данные о 10 000 или 100 000 успешных голов? Его производительность подачи, несомненно, улучшится дальше! Это зависит от вас, чтобы это произошло.

Настоятельно рекомендуется проверить исходный код на Github.Если ваш показатель успеха обучения превышает 60%, оставьте мне сообщение в Twitter (Дружеское напоминание: уровень успеха более 60% определенно может быть достигнут, вы можете вернуться чтобы просмотреть первую GIF-анимацию, проверьте свою тренировку для Xiaohong!)

Подробнее об ИИ:

·  TensorFlow 1.9 официально поддерживает Raspberry Pi

·  Обучите модель в tf.keras с помощью Colab и запустите ее в браузере с помощью TensorFlow.js.

·  Что произойдет, когда TensorFlow представит Swift?

Be a Tensorflower