В PandaScore мы построили модель для отслеживания позиций каждого чемпиона в игре League of Legends (LoL), основываясь исключительно на изображениях мини-карты. В этом более техническом сообщении блога мы расскажем, как мы этого достигли.

Фон

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

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

Миникарта League of Legends (LoL) - отличный пример этой работы. Для этой конкретной задачи наша конкретная цель состояла в том, чтобы создать алгоритм, который может «наблюдать» за миникартой и выводить координаты (x, y) каждого игрока на миникарте.

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

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

Эта проблема

В литературе по глубокому обучению тип проблемы, связанный с просмотром изображений и обнаружением или отслеживанием объектов на этом изображении, обычно называется обнаружением объектов или отслеживанием.

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

Действительно, это был тот подход, который мы попробовали в первую очередь. Опираясь на предыдущую работу над проблемой миникарты LoL, проделанную Фарзейном Маджидом в его проекте DeepLeague, мы обучили модель в стиле SSD на наборе данных Farza DeepLeague100K и обнаружили, что она довольно хорошо работает на протяженном тестовом наборе из его набора данных.

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

Мы потратили несколько недель на изучение нескольких способов решения этой проблемы. Основными вариантами были:

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

В конечном итоге мы выбрали подход 3, который мы опишем более подробно в следующем разделе.

Подход

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

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

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

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

Обучение GAN

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

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

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

Обучение классификатора

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

На приведенной ниже диаграмме показана схема обучения для этого классификатора:

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

Расчет карт обнаружения

Наш классификатор представляет собой полностью сверточную нейронную сеть, которая принимает цветные изображения 24x24 «чемпион на миникарте» в качестве входных данных и выводит тензор 1x1 x (NumChampions + 1). Мы пропускаем этот тензор через нелинейность softmax для оценки вероятностей классов (дополнительный выходной канал предназначен для фонового класса; мы обучили наш классификатор также обнаруживать случайные участки миникарты без чемпиона и выводить высокую «фоновую» вероятность).

Если вместо этого мы передадим этому классификатору весь фрагмент миникарты размером 296x296, мы получим результат 12x12 x (NumChampions + 1). Каждый квадрат сетки 12x12 представляет собой область миникарты, и в каждом из этих квадратов указаны вероятности обнаружения для каждого чемпиона. Мы можем увеличить разрешение этой карты обнаружения до 70x70, уменьшив шаг последних двух слоев нашего классификатора (слой свертки, за которым следует средний слой объединения) до 1, с 2 (это уловка применялась в другом месте, например, в этой работе).

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

Обучение модели последовательности

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

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

На приведенной выше диаграмме представлена ​​архитектура нашей модели последовательности. Мы берем 11 карт обнаружения (D_it), извлеченных, как описано в предыдущем разделе (десять чемпионов + один фон), и пропускаем каждую независимо через ту же свертку, что снижает их разрешение и извлекает релевантную информацию. Копия самого кадрирования миникарты с низким разрешением (M_t) также передается через отдельный сверток, идея заключается в том, что некоторые функции низкого разрешения, касающиеся того, что происходит в игре, также могут быть полезны (например, если есть много действий, то необнаруженные чемпионы, скорее всего, просто спрятаны среди этого действия).

Элементы миникарты и карты обнаружения, извлеченные из этих сверток, затем складываются в один тензор формы 35x35xF, где F - общее количество функций (входные данные миникарты и карты обнаружения имели размер 70x70, а наши свертки уменьшили это разрешение вдвое). Мы называем этот тензор r_t на приведенной выше диаграмме, поскольку у нас есть один из этих тензоров на каждом временном шаге. Эти r_t затем последовательно подаются в сверточный LSTM (подробности реализации conv-LSTM см. В этой статье). Мы обнаружили, что переход с обычного LSTM на сверточный LSTM очень полезен. Предположительно, это произошло потому, что обычному LSTM нужно было изучить один и тот же алгоритм для каждого местоположения на миникарте, тогда как conv-LSTM позволял использовать его для разных местоположений.

На каждом временном шаге каждый из 10 выходных каналов сверточного LSTM (o_it, один i для каждого чемпиона) проходит через один и тот же плотный (полностью связанный) слой. Затем выводятся координаты x и y для каждого чемпиона. Среднеквадратичная ошибка (MSE) между выходными и целевыми координатами затем передается обратно на веса этой сети. Модель сходится примерно через 6 часов обучения на одном графическом процессоре (мы тренировались на собственном наборе данных примерно из 80 игр, который был получен аналогично тому, как описано в Farza).

Полученные результаты

Мы по-прежнему более тщательно изучаем нашу сеть, прежде чем запускать ее в производство. Однако результаты нашего собственного набора тестов показывают, что более 95% всех обнаружений находятся в радиусе 20 пикселей от цели. Ради интереса мы также проверили необходимость дополнения GAN, но обнаружили, что производительность существенно снижается при использовании только стандартного дополнения, в отличие от дополнения с помощью масок, созданных GAN. Кажется, все наши тренировки по GAN не прошли даром :)

В этой статье нет подробностей о реализации, и мы уверены, что некоторые из наших технических читателей захотят узнать больше. Если у вас есть вопросы, не стесняйтесь задавать их здесь, в комментариях, или в ветке r / machinelearning.