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

Обучение с подкреплением

Я был очарован обучением с подкреплением с тех пор, как прочитал о том, что DQN успешно осваивает классические игры Atari. Тогда я потратил некоторое время, пытаясь воссоздать эти результаты, внедрив свой собственный агент Q-обучения и заставив его играть в игры Atari в OpenAI Gym. Без особого успеха. В конце концов я отказался от этого и решил, что мне не хватает не только необходимой теоретической подготовки, но и необходимой вычислительной мощности.

Некоторое время назад я наткнулся на существование алгоритма под названием PPO (Оптимизация проксимальной политики), который должен решить ряд проблем, с которыми обычно сталкивается DQN. Я не претендую на полное понимание различий, но из того, что я понял, PPO считается более стабильным и более универсальным, чем DQN. Мне показалось, что мне нужно еще раз попробовать обучение с подкреплением. Я даже придумал подходящую игровую площадку для своего нового ИИ.

Игра

Недавно я написал небольшую мобильную игру в качестве эксперимента. Игра представляет собой игру типа «три в ряд» (например, Bejeweled или Candy Crush), где уровни постепенно усложняются, пока вы не закончите игру и не должны начать заново с первого уровня.

Пространство наблюдения

За исключением некоторых начальных обучающих уровней, ядром игры является поле из плиток 7x7, каждая из которых содержит один из 5 основных цветов или один из 7 специальных предметов. Количество возможных состояний доски находится где-то между 10³⁴ и 10⁵².

Пространство действий

Цель игры состоит в том, чтобы сгруппировать три или более одного цвета вместе, чтобы создать соответствие. Сопоставляя более трех одновременно, вы получаете специальные предметы с определенным поведением (например, воздушный урон при активации). Позволив агенту провести пальцем по каждой плитке в одном из двух направлений, можно было бы достичь всех возможных целей, что потребовало пространства действия 7x7x2=98 дискретных действий.Позже я понял, что пространство действия можно уменьшить с 14 до 84. но я не изменил свою реализацию и вместо этого продолжил использовать исходное предположение.

Как сделать игру доступной для компьютера

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

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

К счастью, игра написана на Dart, а Dart можно скомпилировать и на настольных компьютерах, и на серверах. Итак, я решил взять исходную игровую логику и обернуть ее REST API. Затем я бы пошел дальше и создал среду Gym, которая использует этот API для игры. Это добавило бы накладные расходы на локальные HTTP-вызовы, но я все равно хотел попробовать.

Итак, вот итоговая архитектура:

Получение рабочего агента PPO

Поскольку моей главной целью было посмотреть, смогу ли я взять существующую реализацию PPO и повторно использовать ее для своих целей, на этот раз у меня не было амбиций написать собственную версию алгоритма. Вот почему я просто взял этот пример PPO с веб-сайта Keras, который был написан для решения среды Cart Pole из OpenAI Gym.

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

Что я узнал, обучая своего агента

Начните с малого

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

Входное кодирование

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

Сетевая архитектура

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

Все эти первоначальные изменения и эксперименты привели к очень хорошим результатам для доски 3x3 с двумя цветами. Вот так выглядела награда во время обучения:

Масштабирование сложно

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

Хотя я был прав в своем предположении, было непросто понять, что нужно сделать, чтобы сделать эту шкалу.

По мере роста я понял, что мой MacBook Pro больше не справляется с обучением — мне нужно было арендовать время графического процессора в облаке, что делало проведение экспериментов очень дорогостоящим. Довольно быстро стало ясно, что размера эпохи в 200 розыгрышей уже недостаточно для получения хороших результатов. В конце концов я остановился на размере эпохи 40 000, из-за чего все последующие эксперименты занимали гораздо больше времени, чем первоначальные.

Самое сложное было то, что долгое время доска 7х7 с 5 цветами просто не работала, что бы я ни пытался. Сначала я подумал, что пространство для действий слишком велико для доски такого размера. Затем я попробовал тренироваться для доски 7x7 только с 4 цветами, и это сработало просто отлично. Поскольку пространство действия зависит от размера доски, а не от количества цветов, размер пространства действия не может быть проблемой.
Я пытался возиться с различными сетевыми архитектурами, с количеством эпох, со скоростью обучения и прочими гиперпараметрами, и ничего не получится.

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

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

Если вам интересно, как выглядела окончательная сетевая архитектура, вот она:

Интеграция агента в игру

Теперь, когда у меня есть обученная модель TensorFlow для агента, мы хотим увидеть, как она играет в игру, верно?

К счастью, есть TensorFlow Lite, который позволяет портировать обученные модели в мобильные приложения. После преобразования модели в модель TensorFlow Lite и интеграции SDK TensorFlow Lite в мою игру я наконец смог увидеть, как агент играет в мою игру.

Итак, как это работает?

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

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

Если вы хотите убедиться в этом сами, вы можете загрузить игру под названием Monster Wipe из Google Play Store или Apple App Store. Начиная с 6-го уровня вы получаете кнопку внизу, которая активирует ИИ и запускает его автоматически.

Для чего его можно использовать?

Балансировка и дизайн уровней

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

NPC или противник

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

Ассистент

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

Последние мысли

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

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

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

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

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

Вы также можете связаться со мной на веб-сайте моей компании или в LinkedIn.