Реализация простой модели обучения с подкреплением с двумя агентами

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

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

Создание крестиков-ноликов в мире RL

Задача крестиков-ноликов - первым поставить свои отметки (крестик или нолик) по горизонтали, вертикали или диагонали. Теперь давайте определим игру в терминах ключевых слов RL, упомянутых ранее:

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

Штат

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

Здесь мы инициализируем нулями доску 3x3, двух игроков и первого игрока, который начнет игру. isEnd - это флаг, указывающий, может ли игра продолжаться или был определен победитель. Каждому игроку назначается конкретный playerSymbol, где p1 представлен цифрами 1 и p2 -1.

getHash - удобная функция, которая выравнивает конфигурацию платы для облегчения последующего анализа. Форма вывода преобразуется из (3,3) в (9,). getAvailablePosition получит набор ящиков на доске, которые еще предстоит занять и, следовательно, будут доступны для следующего хода.

После определения доступных пространств действий для агента, нам нужно определить, как будет определяться победитель (что затем прервет цикл while). Здесь 4 возможных break результата могут быть достигнуты после каждого игрового хода: выигрыш в столбце, выигрыш в ряду, выигрыш по диагонали и ничья.

updateStates будет обновлять конфигурацию платы с текущим playerSymbol после каждого успешного выполнения действия. Затем будет выбран следующий игрок, и игра продолжится. Если игра заканчивается (победой или ничьей), giveReward будет передавать произвольное значение (например, 1 очко выигравшему игроку, 0 проигравшему игроку и 0,1–0,5 обоим в случае ничьей).

Агент

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

Следующие гиперпараметры требуют дополнительных пояснений:

  1. lr (learning_rate) Скорость, с которой обучение выполняется каждым агентом,
  2. decay_gamma Фактор, на который уменьшается награда за ход (т. Е. Заставляет агента выигрывать за наименьшее количество возможных ходов, поскольку выигрыш с большим количеством шагов приводит к уменьшению награды,
  3. exp_rate Скорость исследования, которая позволяет агенту выбирать случайную доступную позицию, а не жадно находить (эксплуатировать) лучший возможный следующий ход из текущего набора изученных политик. Более высокое значение допускает большую случайность в принятии решений агентом.

states будет хранить список конфигураций доски от каждого игрока в данной игре, а states_val - это ключ-значение dict, в котором хранится вознаграждение («значение»), связанное с определенной конфигурацией / состоянием доски («ключ»).

Затем мы определяем chooseAction, который позволяет агенту либо исследовать (выбор случайного действия), либо использовать (выбор действия с наибольшей наградой при текущей конфигурации / состоянии доски).

После того, как агент предпринял какое-либо действие, addStates добавит полученную конфигурацию платы в states. Когда игра закончится, feedReward назначит награду каждой конфигурации (1) в обратном порядке: сначала оценивается последний ход / состояние, и (2) дисконтированным / убывающим образом: наказывается больше ходов.

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

Для обслуживания мы сохраним обученные политики и загрузим их позже, когда будем играть с нашими обученными RL-ботами! :)

Пусть боты играют!

После определения классов States и Player мы собираемся реализовать собственно ход игры!

Функция playBot определена в классе State и служит логикой, по которой мы играем в игру. Два игрока по очереди выбирают действие (случайное или жадное), пока не будет выбран победитель. Затем награда будет назначена обоим агентам в зависимости от значения, которое мы определили ранее.

Позвольте человеку играть!

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

Кроме того, нам также необходимо немного изменить способ определения HumanPlayer: выбор следующего набора действий посредством пользовательского ввода!

Вот и все, круто, правда? Получайте удовольствие, тренируясь самостоятельно! Вы можете проверить полный код и документацию здесь: code.

Подпишитесь на мою информационную рассылку по электронной почте: https://tinyurl.com/2npw2fnz , где я регулярно резюмирую исследовательские работы по ИИ на простом английском языке и в красивой визуализации.

Ссылка

[1] https://github.com/JaeDukSeo/reinforcement-learning-an-introduction