Генетический алгоритм, нейросеть играет в догонялки

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

Модель

Есть две точки. Со значениями x,y. На видео - это сетка (#) и бот (@).

Поведение бота определенно заранее. Он двигается в сторону сетки с максимальной скоростью. Как только бот настигнет сетку - игра окончена. Количество очков зависит от того, как долго сетка сможет убегать. Я ограничил в 10000 тактов макс, чтобы не зависло. Когда сетке удастся набегать 10000 тактов - это победа.

И у сетки и у бота есть максимальная скорость и размер (5). Скорость бота - 1, сетки - 2. Сетка может двигаться с любой скоростью в пределах максимальной. Бот - всегда с максимальной. Поле ограничено: 400х225.

Нейронка

Тут все просто как два пальца. Feedforward сеть. На вход 4 значения: угол и расстояние между ботом и сеткой, и положение x,y сетки на экране. Нормализация: угол делится на ПИ, расстояние - на диагональ поля. Положения на экране делятся на ширину и высоту поля. Получается нормализованный вектор в 4 значения.

Нейронная сеть с прямой связью (FNN) — это один из двух широких типов искусственных нейронных сетей, характеризующийся направлением потока информации между ее слоями. (В одном направлении - от входа к выходу).

Два скрытых слоя, по 12 нейронов на каждый. Связи между каждым слоем - полные (full join) - каждый нейрон входного слоя с каждым нейроном выходного.

Выходной слой - 2 значения. Угол движения сетки и скорость. Активация через гиперболический тангенс. O(x)=tanh(sum(x)+bias)

FNN
FNN

Исходные значения весов и bias задаются случайно, в диапазоне [-0.5; 0.5]

Мутация

Обучается сетка без учителя. На каждое поколение (ограничил 10000 макс) - создается уникальная среда и мутации. Сначала создается мутация, есть 5% шанс, что bias или вес изменятся. Сила изменения bias (смещения) - 0.4, веса - 0.4. Т.е. вес и смещение изменится на случайную величину в диапазоне [-0.2, 0.2]. Всего на каждое поколение создается 20 мутантов. Каждый играет в изолированной среде, мутант победитель дает следующее поколение.

Каждый мутант играет 5 игр. Тот, что в сумме наберет наибольшее количество очков - побеждает. Каждую игру положение и сетки и бота - случайное.

Реализация

Писал на C#. Изначально делал на JS, но возникла потребность в производительности, обучение - ресурсозатратный процесс. Сетка учится избегать бота в среднем за 750-1200 поколении. Особо сильно с оптимизацией не запаривался - но думаю, вполне возможно достичь 2-5 минут на полное обучение при текущей конфигурации. Т.о. доказана возможность обучения через игру. (Up: ~400 поколений в минуту после распараллеливания)

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

Дальнейшие планы

Кровь из носу нужно определить, как подгонять динамическую размерность входных данных для входа сети. Задал вопрос на QA - пока что предложили только то, что я и сам знаю. В любом случае буду добавлять еще ботов и смотреть - как сетка будет себя вести (UP: боты тупо слиплись в одну точку, а дальше все так же). Скорее всего заменю абсолютное положение сетки на относительное (инерцию, т.е. разницу текущего и предыдущего положения), т.к. иначе она может не адекватно реагировать на препятствия. Хочу добавить и иные элементы на экране по вкусу - препятствия, бафы и т.д. Так же хочу заменить бота на другую сетку и научить ее ловить своих собратьев и сосистер.

В целом - тренд на онлайн игру "Нейромоны". Тренер нейромона обучает, размножает, скрещивает и меняется ими с другими тренерами. Нейромоны могут играть на турнирах с нейромонами других тренеров. На сервере создается уникальный уровень для того или иного типа игры, нейромоны зарабатывают победы, рейтинг и места в турнирных таблицах. В общем, как игра "покемоны" - но с реальной обучаемой моделью и абсолютно уникальной сеткой внутри. Эффективность задается не только "типом" покемона и его статами, а реальной приспособленностью к тем или иным игровым ситуациям. Для тренера - зиро кодинг и контроль, лишь менеджмент и стратегическое планирование. А так - просто делаю Zomoby, но которая играет сама в себя еще больше. Это кста камень в огород Gaijin Entertainment - мне тогда их тимлид сказал, мол сама в себя играет. И тут бац - 5 лет спустя стреляет Vampire Surivors.

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

Благодарю за внимание.

UP: Все то-же, но сетка достигла 5000 тактов на ~200 поколении за ~30 сек.

После чего я добавил на вход изменение сетки в пространстве (значения dx,dy, которые отражают, как сильно сдвинулась сетка в пространстве. Если уперлась в стену - независимо от ее скорости - двигаться не будет, поэтому dx=0 или dy=0). Сетка нашла решение на 5000 тактов за (примерно) 135 поколений и 16 секунд.

@ildarin
15.08.2023 06:42 UTC
Первоисточник

Комментарии

@MKMatriX
15.08.2023 01:44 UTC
0

На js квадратики учатся играть во флаппи берд) https://mkmatrix.github.io/flappynn.github.io/ где-то 300 поколений уходит)

@ildarin
15.08.2023 01:55 UTC
0

Ага, я статью даж видал) https://habr.com/ru/articles/336612/

У меня кста сигимоида чот не работала.

@forthuse
15.08.2023 04:57 UTC
+1

А, если и бот — обучающаяся нейросетка,
то какие прогнозы обучения обеих агентов в этой модельной ситуации? :)

@ildarin
15.08.2023 05:52 UTC
0

Если бот только 1 - то должен двигаться аналогично "тупому" боту. Но есть нюанс - углы и стены. Если двигаться на упреждение - то можно не выпустить из угла. А значит первому нужно избегать краев поля.

Но тогда в идеале еще инерцию добавить: dx+=cos(a)*force; x=x+dx; dx*=0.98;

@LewXie
15.08.2023 17:28 UTC
+3

Почему именно генетика, а не, например, Q-learning?

@ildarin
15.08.2023 20:45 UTC
+1

Видел мельком, но подробно не изучал. С вашей подачи немного ознакомился) Как раз мой случай описан, про "аниматы", но с лучами-сенсорами. Делал до этого похожее на Q-learning - у сетки был выход на каждое возможное действие, выход с максимальным значением определял выбранное действие (может это и есть Q-learning? Хз, делал интуитивно). Результат мне не очень понравился, хоть он и удивил. А так - биологию люблю.

16.08.2023 03:18 UTC
+2

Вот туториал есть, если хотите попробовать: https://pytorch.org/tutorials/intermediate/reinforcement_q_learning.html
Я когда-то игрался, сейчас сам уже не помню ничего ?

16.08.2023 04:18 UTC
+1

Спасибо! Питон к сожалению не знаю - по "идеологическим" причинам) Я так понял - оценка должна быть каждый такт?

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

16.08.2023 06:47 UTC
+2

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

@ildarin
24.08.2023 05:42 UTC
+1

Для Q-learning нужен набор возможных действий, ведь так?

Сетке нужно определить направление и силу движения. У меня направление и сила движения в dobule, 64bit или 18446744073709551615 состояний для каждого параметра. Это 18446744073709551615 в квадрате = 340,282,366,920,938,463,426,481,119,284,349,108,225 состояний. Это 340 ундециллионов. Я же все верно рассчитал?

24.08.2023 06:20 UTC
+1

Да, сам по себе Q-learning используется для систем с маленьким дискретным пространством возможных действий. Но можно использовать actor-critic. Вот, кстати, курс есть: https://huggingface.co/learn/deep-rl-course/unit6/advantage-actor-critic

24.08.2023 07:07 UTC
+1

Не понимаю, как actor-critic может решить проблему огромного множества дискретных состояний? Я вижу решение лишь снижением размерности.

24.08.2023 07:22 UTC
+1

Просто actor будет предсказывать действие, как и сейчас у Вас он делает, а critic получать на вход действие+среда и считать награду. Соответственно, critic обучается на известной последовательности ходов, как в q-learning, а actor в связке с critiс, чтобы для заданного состояния среды максимизировать награду

24.08.2023 09:45 UTC
+1

Спасибо за разъяснение, понял.

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

@imageman
21.09.2023 10:04 UTC
+1

Тут нужно сделать жирный комментарий. Генетическим алгоритмам я посвятил лет 15, в основном разными исследованиями баловался. В результате пришел к таким выводам: в любой более-менее сложной задаче нужно закладывать 1 миллион вычислений целевой функции. Дальше смотрим время 1 вычисления и примерно поймем минимальное время нужное для подгонки. Задача должна быть не слишком овражной. Про плюсы и минусы не буду писать. Конкретно в твоем случае (нахождение оптимальных весов нейросети) я бы тебе посоветовал алгоритм имитации отжига (раз ты игнорируешь метод обратного распространения ошибки!). Имитация отжига тоже очень простой алгоритм и он в твоем случае может дать лучше результат.