Очень интересно | 21 От FlappyBird к DQN

искусственный интеллект GitHub Нейронные сети игра
Очень интересно | 21 От FlappyBird к DQN

Введение

Познакомить с концепцией обучения с подкреплением (RL) и использовать DQN для обучения модели, которая может играть во FlappyBird.

FlappyBird

Многие люди играли в эту игру, она очень жестокая, ниже показан FlappyBird, воспроизведенный с помощью pygame,GitHub.com/sour AB Fire v/FL…

Установите, если у вас нет pygame

pip install pygame

бегатьflappy.pyВы можете начать игру.Если кнопки не управляются, используйтеpythonwПросто запустите код

pythonw flappy.py

FlappyBird游戏截图

принцип

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

РЛ состоит из нескольких компонентов:

  • Состояние (S): Состояние среды, например, текущий игровой интерфейс в FlappyBird, может быть представлено изображением.
  • Действие (A): набор действий, которые можно выполнить под каждым S, например, во FlappyBird можно выбрать два A, «прыгать» или «ничего не делать».
  • Награда (R): Награда, которую вы получаете после выполнения A под определенным S, например, в FlappyBird, это может быть успешный прыжок через водопроводную трубу (положительная награда), удар по водопроводной трубе или падение на землю (отрицательная награда). награда)

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

s_0,a_0,r_1,s_1,a_1,r_2,s_2,...,s_{n-1},a_{n-1},r_n,s_n

Определите функцию, которая вычисляет сумму вознаграждений в течение игры.

R=r_1+r_2+r_3+...+r_n

и сумма возвратов с определенного момента

R_t=r_t+r_{t+1}+r_{t+2}+...+r_n

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

R_t=r_t+\gamma r_{t+1}+\gamma^2 r_{t+2}+...+\gamma^{n-t} r_n

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

R_t=r_t+\gamma R_{t+1}

DQN — это распространенный алгоритм обучения с подкреплением, который в основном вводит функцию Q (качество, функция ценности) для расчета максимальной общей отдачи, которую можно получить, выполнив определенный A при определенном S

Q(s_t,a_t)=\max R_{t+1}

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

\pi(s)=argmax_a Q(s,a)

Когда функция Q сходится, рекурсивная формула функции Q также может быть получена

Q(s_t,a_t)=r_t+\gamma \max Q(s_{t+1},a_{t+1})

Q-функцию можно реализовать и обучить с помощью нейронной сети:

  • Определите структуру нейронной сети и инициализируйте ее случайным образом, вход S, а количество выходов совпадает с размером набора действий.
  • Каждый раз А выбирается случайным образом с определенной вероятностью, в противном случае оптимальная А выбирается с помощью функции стратегии, то есть комбинации случайного исследования и направленной стратегии
  • Поддерживать модуль памяти для накопления данных, сгенерированных во время игры.
  • Период прогрева: без обучения, в основном для того, чтобы модуль памяти сначала накопил определенный объем данных
  • Период исследования: постепенно уменьшайте случайную вероятность, переходите от случайного исследования к направленной стратегии и каждый раз берите некоторые данные из модуля памяти для обучения модели.
  • Период обучения: фиксированная случайная вероятность, дальнейшее обучение модели, чтобы функция Q еще больше сходилась

Для ознакомления с принципами обучения с подкреплением и DQN вы можете обратиться к следующим статьям:Love.Intel.com/demystify в…

выполнить

Изменено на основе следующих элементов,GitHub.com/Также Чен Линь/…

gameКод в предыдущемflappy.pyУпрощено и изменено, удалено фоновое изображение и исправлен цвет персонажа и водопроводной трубы, игра запустится автоматически и продолжится автоматически после зависания, в основном для облегчения автоматической модели и сбора данных.

загрузить библиотеку

# -*- coding: utf-8 -*-

import tensorflow as tf
import numpy as np
import random
import cv2
import sys
sys.path.append('game/')
import wrapped_flappy_bird as fb
from collections import deque

определить некоторые параметры

ACTIONS = 2
GAMMA = 0.99
OBSERVE = 10000
EXPLORE = 3000000
INITIAL_EPSILON = 0.1
FINAL_EPSILON = 0.0001
REPLAY_MEMORY = 50000
BATCH = 32
IMAGE_SIZE = 80

Определите некоторые сетевые входы и вспомогательные функции, каждая S состоит из четырех последовательных скриншотов игры.

S = tf.placeholder(dtype=tf.float32, shape=[None, IMAGE_SIZE, IMAGE_SIZE, 4], name='S')
A = tf.placeholder(dtype=tf.float32, shape=[None, ACTIONS], name='A')
Y = tf.placeholder(dtype=tf.float32, shape=[None], name='Y')
k_initializer = tf.truncated_normal_initializer(0, 0.01)
b_initializer = tf.constant_initializer(0.01)

def conv2d(inputs, kernel_size, filters, strides):
    return tf.layers.conv2d(inputs, kernel_size=kernel_size, filters=filters, strides=strides, padding='same', kernel_initializer=k_initializer, bias_initializer=b_initializer)

def max_pool(inputs):
    return tf.layers.max_pooling2d(inputs, pool_size=2, strides=2, padding='same')

def relu(inputs):
    return tf.nn.relu(inputs)

Определить структуру сети, типичную свертку, пул, структуру полносвязного слоя.

h0 = max_pool(relu(conv2d(S, 8, 32, 4)))
h0 = relu(conv2d(h0, 4, 64, 2))
h0 = relu(conv2d(h0, 3, 64, 1))
h0 = tf.contrib.layers.flatten(h0)
h0 = tf.layers.dense(h0, units=512, activation=tf.nn.relu, bias_initializer=b_initializer)

Q = tf.layers.dense(h0, units=ACTIONS, bias_initializer=b_initializer, name='Q')
Q_ = tf.reduce_sum(tf.multiply(Q, A), axis=1)
loss = tf.losses.mean_squared_error(Y, Q_)
optimizer = tf.train.AdamOptimizer(1e-6).minimize(loss)

Реализовать модуль памяти с очередью, запустить игру и ничего не делать для выбора начального состояния

game_state = fb.GameState()
D = deque()

do_nothing = np.zeros(ACTIONS)
do_nothing[0] = 1
img, reward, terminal = game_state.frame_step(do_nothing)
img = cv2.cvtColor(cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE)), cv2.COLOR_BGR2GRAY)
_, img = cv2.threshold(img, 1, 255, cv2.THRESH_BINARY)
S0 = np.stack((img, img, img, img), axis=2)

Идите вперед и играйте в игру и тренируйте модель

sess = tf.Session()
sess.run(tf.global_variables_initializer())

t = 0
success = 0
saver = tf.train.Saver()
epsilon = INITIAL_EPSILON
while True:
    if epsilon > FINAL_EPSILON and t > OBSERVE:
        epsilon = INITIAL_EPSILON - (INITIAL_EPSILON - FINAL_EPSILON) / EXPLORE * (t - OBSERVE)

    Qv = sess.run(Q, feed_dict={S: [S0]})[0]
    Av = np.zeros(ACTIONS)
    if np.random.random() <= epsilon:
        action_index = np.random.randint(ACTIONS)
    else:
        action_index = np.argmax(Qv) 
    Av[action_index] = 1

    img, reward, terminal = game_state.frame_step(Av)
    if reward == 1:
        success += 1
    img = cv2.cvtColor(cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE)), cv2.COLOR_BGR2GRAY)
    _, img = cv2.threshold(img, 1, 255, cv2.THRESH_BINARY)
    img = np.reshape(img, (IMAGE_SIZE, IMAGE_SIZE, 1))
    S1 = np.append(S0[:, :, 1:], img, axis=2)

    D.append((S0, Av, reward, S1, terminal))
    if len(D) > REPLAY_MEMORY:
        D.popleft()

    if t > OBSERVE:
        minibatch = random.sample(D, BATCH)
        S_batch = [d[0] for d in minibatch]
        A_batch = [d[1] for d in minibatch]
        R_batch = [d[2] for d in minibatch]
        S_batch_next = [d[3] for d in minibatch]
        T_batch = [d[4] for d in minibatch]

        Y_batch = []
        Q_batch_next = sess.run(Q, feed_dict={S: S_batch_next})
        for i in range(BATCH):
            if T_batch[i]:
                Y_batch.append(R_batch[i])
            else:
                Y_batch.append(R_batch[i] + GAMMA * np.max(Q_batch_next[i]))

        sess.run(optimizer, feed_dict={S: S_batch, A: A_batch, Y: Y_batch})

    S0 = S1
    t += 1

    if t > OBSERVE and t % 10000 == 0:
        saver.save(sess, './flappy_bird_dqn', global_step=t)

    if t <= OBSERVE:
        state = 'observe'
    elif t <= OBSERVE + EXPLORE:
        state = 'explore'
    else:
        state = 'train'
    print('Current Step %d Success %d State %s Epsilon %.6f Action %d Reward %f Q_MAX %f' % (t, success, state, epsilon, action_index, reward, np.max(Qv)))

бегатьdqn_flappy.pyВы можете обучать модель с нуля.В начале персонаж прыгает по-разному, и даже водопровод не может через него перепрыгнуть, но по мере обучения персонаж будет получать все более и более стабильные показатели за счет обучения.

DQN模型运行结果

Вы также можете запустить обученную модель напрямую с помощью следующего кода

# -*- coding: utf-8 -*-

import tensorflow as tf
import numpy as np
import cv2
import sys
sys.path.append('game/')
import wrapped_flappy_bird as fb

ACTIONS = 2
IMAGE_SIZE = 80

sess = tf.Session()
sess.run(tf.global_variables_initializer())

saver = tf.train.import_meta_graph('./flappy_bird_dqn-8500000.meta')
saver.restore(sess, tf.train.latest_checkpoint('./'))
graph = tf.get_default_graph()

S = graph.get_tensor_by_name('S:0')
Q = graph.get_tensor_by_name('Q/BiasAdd:0')

game_state = fb.GameState()

do_nothing = np.zeros(ACTIONS)
do_nothing[0] = 1
img, reward, terminal = game_state.frame_step(do_nothing)
img = cv2.cvtColor(cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE)), cv2.COLOR_BGR2GRAY)
_, img = cv2.threshold(img, 1, 255, cv2.THRESH_BINARY)
S0 = np.stack((img, img, img, img), axis=2)

while True:
    Qv = sess.run(Q, feed_dict={S: [S0]})[0]
    Av = np.zeros(ACTIONS) 
    Av[np.argmax(Qv)] = 1

    img, reward, terminal = game_state.frame_step(Av)
    img = cv2.cvtColor(cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE)), cv2.COLOR_BGR2GRAY)
    _, img = cv2.threshold(img, 1, 255, cv2.THRESH_BINARY)
    img = np.reshape(img, (IMAGE_SIZE, IMAGE_SIZE, 1))
    S0 = np.append(S0[:, :, 1:], img, axis=2)

Ссылаться на

видеоурок

Глубоко и интересно (1)