- PVSM.RU - https://www.pvsm.ru -

Как учиться с помощью машинного обучения у экспертов в Dota 2

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

Как учиться с помощью машинного обучения у экспертов в Dota 2 - 1

О себе

Зовут меня Никита Сазанович. До июня 2018 года я три года учился в СПбАУ, а затем вместе с остальными моими одногруппниками перевелся в ВШЭ СПб, где и заканчиваю сейчас бакалавриат. С недавнего времени я также работаю исследователем в JetBrains Research. До поступления в университет я увлекался спортивным программированием и выступал за сборную Беларуси.

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

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

Агенты оперируют на состояниях и выбирают действия. Например, в задаче о выходе из лабиринта нашими состояниями будут координаты x и y, а действиями движения вверх/вниз/влево/вправо. Общая же схема выглядит вот так:

Как учиться с помощью машинного обучения у экспертов в Dota 2 - 2

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

Решить эту проблему можно, дав агенту на старте примеры того, как "нужно играть" — так называемые демонстрации экспертов.

Задача для обучения

Модельная задача, о которой пойдет речь в статье — это Dota 2.

Dota 2 — это популярная MOBA игра, в которой команда из пяти героев должна победить команду соперника, уничтожив их "крепость". Dota 2 считается довольно сложной игрой, в ней есть esports с призовыми на главном турнире в $25000000 [1].

Вы могли слышать про недавние успехи OpenAI в Dota 2. Сначала они создали бота для игры один на один и победили профессиональных игроков [2], а потом перешли к игре 5x5 и этим летом показали впечатляющие результаты [3], хотя и проиграли профессиональным командам.

Как учиться с помощью машинного обучения у экспертов в Dota 2 - 3

Единственной проблемой является то, что обучали они агента для игры один на один, по их же словам [4], на 60000 ЦПУ и 256 K80 GPU на облаке Azure. У них, конечно, есть возможность заказать столько мощи. Но если у вас мощности меньше, то приходится применять хитрости. Одной из такой хитростей и является использование уже сыгранных людьми игр.

Демонстрации в игре

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

Более масштабная и авантюрная цель — это достать большее количество данных из открытого доступа. Одной из причин при выборе Dota 2 для ускорения обучения был такой ресурс, как dotabuff [5]. Там собрана разная статистика по игре, но более важно то, что там есть полные реплеи игр. И их можно сортировать по рейтингу.

Пока я еще не опробовал, как сильно поможет гигабайт таких данных в сравнении с несколькими эпизодами. Реализовать же сбор данных было довольно просто: вы получаете ссылки на игры на dotabuff, скачиваете игры и пользуетесь парсером игр Dota 2 [6].

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

У нас есть игра Dota 2, клиент которой существует под платформы Windows, Linux и macOS. Но все же обычно обучение происходит в каком-то скрипте на python, и в нем вы создаете среду, будь то лабиринт, подъем машины на горку [7] или что-то в таком роде. Но среды для Dota 2 нет. Поэтому мне самому пришлось создавать эту обертку, что было довольно интересно технически. Получилось это сделать так:

Как учиться с помощью машинного обучения у экспертов в Dota 2 - 4

Первая часть — это скрипт для общения с клиентом игры. К счастью, для Dota 2 есть официальный API для создания ботов: Dota Bot Scripting [8]. Реализован он как вставки на языке Lua, который, как оказалось, популярен в разработке игр. Скрипт бота же, взаимодействуя с клиентом игры, вытаскивает в нужный момент интересную нам информацию (например, координаты на карте, позиции противников) и отправляет json с ней на сервер.

Вторая часть — это собственно сама обертка. Это оформлено в виде сервера, который обрабатывают всю логику запуска Steam-а, Dota-ы и получением json-ов от скрипта внутри игры. Управление запуском игр и клиентов устроено через pyautogui [9], а общение с lua-вставкой в игре — через Flask сервер.

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

Учимся у экспертов

Сам алгоритм не особо важен в этой статье, ведь эти техники можно применять с любым алгоритмом. Мы использовали DQN (о котором можно почитать на хабре [10]). По сути, это глубокая нейронная сеть + алгоритм Q-обучения [11]. Да, это именно тот DQN, который создал DeepMind, чтобы играть в Atari игры.

Здесь же интереснее рассказать о том, как использовать предыдущие игры. Я испытал два подхода: potential-based reward shaping и action advice.

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

Суть potential-based reward shaping в том, что какие-то состояния нам изначально кажутся более перспективными чем другие, и на основе этого мы модифицируем реальные награды, которые получает алгоритм. Делаем мы это вот таким образом: $r' leftarrow r + gammaPhi(s_{t+1})-Phi(s_t)$, где $r'$ — награда модифицированная, $r$ — награда реальная, $gamma$ — discount factor из алгоритма обучения (не особо нам важен), а вот $Phi(s_t)$ и есть наш потенциал для состояния, которое мы посетили во время $t$. Простой пример — это преодоление лабиринта.

Допустим, есть лабиринт, в котором мы хотим из клетки (0,0) прийти в клетку (5,5). Тогда нашим потенциалом для состояния (x,y) может стать минус евклидово расстояние от (x,y) до нашей цели (5,5): $Phi((x,y))=-sqrt{(x-5)^2+(y-5)^2}$. То есть чем ближе мы к финишу, тем больший потенциал у состояния (к примеру, $Phi((5,5))=0$, $Phi((2,3))~=-3.61$, $Phi((1,5))=-4$). Так мы мотивируем агента любыми способами приближаться к цели.

Для Dota 2 идея такая же, но потенциалы задаются немного сложнее:

Как учиться с помощью машинного обучения у экспертов в Dota 2 - 15

Представьте, что мы просто хотим пройти по тем же состояниям, что и демонстратор. Тогда чем больше состояний мы пройдем, тем выше потенциал. Мы ставим потенциал состояния по проценту завершения реплея, если там есть состояние, близкое нашему. Это имеет разный смысл в различных задачах. Но именно в Dota 2 это означает, что сначала мы хотим, чтобы бот дошел до центра (ведь в начале демонстраций есть только шаги к центру), а потом держался состояний игрока-человека (большое здоровье, безопасное расстояние до противников и т.д.).

Второй же метод, action-advice, был взят из этой статьи [12]. Его суть в том, что сейчас мы советуем агенту не полезность состояний, а полезность действий. Например, в нашей игре Dota 2 могут быть такие советы: если около тебя есть вражеский миньон, то атакуй его; если же ты не дошел до центра, то иди в его направлении; если теряешь здоровье, то отступай к своей башне. И в этой статье описан метод задания таких советов без каких-нибудь раздумий самим программистом — автоматически.

Потенциалы сгенерированы по такому принципу: потенциал действия $a$ в состоянии
$s$ увеличивается при наличии близких состояний $s_d$ с таким же
действием $a$ в демонстрациях. Дальше награда за действие на схеме выше
изменяется как $ r' leftarrow r + gamma Phi(s_{t+1}, a'_{t+1}) - Phi(s_t, a_t)$.
Здесь стоит заметить, что потенциалы мы задаем уже для действий в состояниях.

Результаты

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

Обучение агента с использованием любого из подходов занимает всего 20 часов на персональном компьютере (большую часть времени занимает отрисовка игры Dota 2), а судя по графикам OpenAI, обучение на их серверах идет на порядки недель.

Небольшая выдержка игры при использовании подхода potential-based reward shaping:

И для подхода action advice:

Эти записи были сделаны на скорости тренировки — x10. Все еще видны неточности в поведении агента при перемещении к центру, но все равно борьба в центре показывает выученные маневры. К примеру, отступление назад при малом здоровье.

Также можно видеть разницы подходов: при potential-based reward shaping агент передвигается плавно, т.к. "идет по потенциалу"; при action advice бот играет более агрессивно в центре, так как получает подсказки по атаке.

Итоги

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

Прежде всего, мне в этой статье хотелось показать, что в случае обучения с подкреплением вам не всегда нужно выбирать между очень простой средой (побег из лабиринта) или очень большой стоимостью обучения (по моим беглым подсчетам, OpenAI обходились те сервера для обучения на Azure $4715 в час). Существуют техники, которые позволяют ускорить обучение, и я рассказал лишь об одной из них — использование демонстраций. Важно отметить, что таким образом вы не просто повторяете демонстратора, а лишь "отталкиваетесь" от него. Важно, что при дальнейшем обучении у агента есть возможность превзойти экспертов.

Если вам интересны детали, то код процесса обучения можно найти на GitHub [13].

Автор: miksaz

Источник [14]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/algoritmy/304836

Ссылки в тексте:

[1] $25000000: https://liquipedia.net/dota2/The_International/2018

[2] победили профессиональных игроков: https://blog.openai.com/dota-2/

[3] впечатляющие результаты: https://blog.openai.com/the-international-2018-results/

[4] по их же словам: https://blog.openai.com/openai-five/

[5] dotabuff: https://www.dotabuff.com

[6] парсером игр Dota 2: https://github.com/skadistats/clarity

[7] подъем машины на горку: https://habrastorage.org/webt/t4/-t/7l/t4-t7lcdrwmeqilqr-xx5qmqneg.jpeg

[8] Dota Bot Scripting: https://developer.valvesoftware.com/wiki/Dota_Bot_Scripting

[9] pyautogui: https://pyautogui.readthedocs.io

[10] почитать на хабре: https://habr.com/post/279729/

[11] Q-обучения: https://ru.wikipedia.org/wiki/Q-%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5

[12] статьи: https://www.ijcai.org/Proceedings/15/Papers/472.pdf

[13] GitHub: https://github.com/niksaz/dota2-expert-demo

[14] Источник: https://habr.com/post/435636/?utm_campaign=435636