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

Эта статья проведет вас через упрощенную игру, в которой используется обучение с подкреплением на основе Q-таблиц и которую легко визуализировать с помощью Tkinter. Цель игры - научить случайно движущийся зеленый шар достичь центра небольшого круга. Если мяч не достигает точки в течение 200 шагов, он проигрывает и игра начинается заново.

Весь код для запуска тренировки RL и ее визуализации доступен здесь

Есть 3 вещи, которые необходимо определить для проведения любого обучения RL.

  1. Агент: это компонент игры, который изучает политику и принимает решения. В нашей игре агент - это зеленый шар.
  2. Состояние. Думайте о состоянии как о «описании» агента в определенный момент игры. Состояние должно фиксировать всю информацию, необходимую, чтобы решить, достигнута ли конечная цель (или промежуточная цель) агента. Эта информация должна быть необходимой и достаточной. В нашей игре состояние фиксируется двумерными координатами зеленого шара. Их достаточно, чтобы сказать нам, достиг ли мяч желаемой конечной позиции или нет.
  3. Действие: действие - это все, что изменяет состояние агента. Обычно агент имеет конечный набор возможных действий, которые он может предпринять в любом данном состоянии. Выбор наилучшего действия изначально является случайным (фаза исследования), когда агент пытается выяснить, каковы последствия выполнения выбранного действия. Как только агент начинает набираться опыта в нескольких раундах игры, он начинает разрабатывать политику, которая направляет его выбор действия, а не случайное исследование. Это то, что мы называем фазой эксплуатации. В нашей игре агент может выбрать только 8 возможных направлений. Но мы дали ему возможность переместить каждую сторону на 10 или 20 пикселей. Таким образом, размер действия равен 16.

Давайте рассмотрим код для настройки пространства состояний (набора всех возможных состояний) и пространства действий (набора всех возможных действий) для нашей игры.

mov_list = [-20,-10,10,20]
#Set up Q table
state_space = {}
temp_list = []
for n in range(0,500,10):
 for m in range(0,360,10):
  temp_list.append((n,m))
for k in range(1800):
 state_space[k] = temp_list[k]
action_space = {}
temp_list = []
for n in mov_list:
 for m in mov_list:
  temp_list.append((m,n))
for k in range(16):
 action_space[k] = temp_list[k]

В этом коде предполагается, что игровое окно имеет размер 500 x 360 пикселей. Итак, наше пространство состояний должно иметь размер 18000 (каждый пиксель x, y, которого может достичь агент). Но мы определили возможные перемещения (mov_list) только в количестве, кратном 10. Таким образом, это сжимает наше пространство состояний в 10 раз до 1800. Пространство действий аналогично состоит из всех возможных перемещений (комбинации x и y), что дает набор из 16.

Итак, теперь мы определили агента, состояние и действие для нашей игры. Но вопрос в том, как агент узнает, полезно ли предпринимаемое им действие? Здесь вступает в действие функция вознаграждения. Награды (или штрафы) могут быть предоставлены после каждого действия или в конце игры. Как правило, рекомендуется сохранять простую систему вознаграждений. Например, в нашей игре мяч имеет максимум 200 шагов, чтобы достичь круга. За каждый шаг нет награды. Если мяч находит круг до 200 шагов, то дается награда в 100.

Итак, как эта награда используется для создания политики? Есть несколько способов сделать это, но мы использовали Q-таблицы, которые являются одним из самых простых инструментов для обновления политики. Q-таблица - это просто матрица пространства состояний x пространства действий.

q_table = np.zeros([len(state_space),len(action_space)])

Для нашей игры это матрица 1800 x 16, инициализированная 0 для каждой ячейки. Если какое-либо действие приводит к вознаграждению, мы обновляем таблицу Q для соответствующего состояния, пары действий.

old_q_value = q_table[state, action]
  next_state = list(state_space.keys())[list(state_space.values()).index((pos_x1, pos_y1))]
  next_max = np.max(q_table[next_state])
  q_target = reward + gamma * next_max
  q_delta = q_target - old_q_value
  q_table[state, action] = old_q_value + alpha * q_delta

Я ввел здесь два новых термина. «Альфа» устанавливает скорость обучения для алгоритма, а «гамма» - коэффициент дисконтирования для будущих вознаграждений. Более высокое значение гаммы придает большее значение возможным будущим вознаграждениям. Мы использовали альфа 0,9 и гамму 1.

Остается одна вещь. Установка соотношения разведки и эксплуатации. Это устанавливается термином эпсилон. Если случайное число (от 0 до 1) ниже эпсилон, то агент может исследовать и игнорировать текущую политику в соответствии с таблицей Q.

if random.random() < epsilon:
    x1 = random.choice(mov_list)
    y1 = random.choice(mov_list)
    action = list(action_space.keys())[list(action_space.values()).index((x1, y1))]
   else:
    action = np.argmax(q_table[state])
    x1, y1 = action_space[action]

Весь сценарий доступен здесь

Лучший способ визуализировать, как работает обучение с подкреплением, - это отслеживать движение мяча через некоторый графический интерфейс. Я сохранил код RL отдельно от кода визуализации, чтобы RL работал очень быстро. Вы можете запустить RL для определенного количества игр (параметр эпизодов в коде), а затем запустить графический интерфейс, чтобы увидеть, как ведет себя мяч. Графический интерфейс основан на Tkinter и должен легко работать на любой платформе. Главное помнить, что epsilon установлен в 0 для прогонов RL. Таким образом, он полностью исследует все игры во время обучения RL (и выстраивает политику). Не стесняйтесь устанавливать его выше и наблюдать за результатами в графическом интерфейсе.

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

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