前言

我们的目标是训练小鸟尽可能地保持存活通过更多的管道障碍物从而最大化游戏得分。当很难完全罗列预定的行为进行编程时,就可采用强化学习方式。

我们计划设计一个强化学习系统,其中Q函数通过一个卷积神经网络(深度Q网络)来模拟,其输入是原始像素,输出是一个评估未来奖励的价值函数,通过该价值函数来指导智能体采取动作。深度Q网络的训练是提取游戏运行的图像,并输出从可采取的操作集合中提取的必要执行动作。这相当于一个分类问题,不过与常见的分类问题不同,这里无法使用带标记的数据来训练模型,而是可以采用强化学习,根据执行游戏并基于所观察到的奖励来评价一个给定状态下的动作,以此来进行模型训练。

一、强化学习系统

【FlappyBird小游戏】编写AI逻辑(一)——RL系统和数据预处理_游戏开发

二、帧数据的预处理

1、抓取帧图像

获取基于PyGame的游戏窗口的每一帧渲染的画面:

image_data = pygame.surfarray.array3d(pygame.display.get_surface())

其中pygame.display.get_surface() 用于获取当前显示的Surface对象,其中Surface对象是Pygame 中用于表示图像的对象。

pygame.surfarray.array3d() 将像素的RGB的颜色整数值拷贝到是一个三维数组中。

2、预处理初始状态

初始状态是抓取的第1帧图像,但是我们的状态需要连续4帧,这里我们直接将第一帧图像重复4次作为获取的游戏初始状态:

# 预处理函数,获取初始状态
def get_init_state(self, x_rgb):
    x_rgb = cv2.resize(x_rgb, (80, 80))  # 将RGB图像进行缩放
    x_gray = cv2.cvtColor(x_rgb, cv2.COLOR_BGR2GRAY)  # 将RGB图像转换为灰度图像
    ret, x_t = cv2.threshold(x_gray, 1, 255, cv2.THRESH_BINARY)  # 将灰度图像进行二值处理,将大于等于1的索引变化为255,等于0的不变
    state = np.stack((x_t, x_t, x_t, x_t), axis=2)  # 将一帧图像拼接,使得图片的维度为[80, 80, 4]
    return state

其中np.stack((x_t, x_t, x_t, x_t), axis=2)将一帧图像拼接,使得图片的维度为[80, 80, 4],其中参数(x_t, x_t, x_t, x_t) 表示需要进行串接的图片, axis = 2 表示在第三个维度上进行串接操作。

3、预处理下一状态

同样获取游戏下一状态的相关函数如下:

# 预处理函数,将当前状态和新一帧画面处理成新状态
def get_next_state(self, state, x_rgb):
    x_rgb = cv2.resize(x_rgb, (80, 80))  # 将RGB图像进行缩放
    x_gray = cv2.cvtColor(x_rgb, cv2.COLOR_BGR2GRAY)  # 将RGB图像转换为灰度图像
    ret, x_t = cv2.threshold(x_gray, 1, 255, cv2.THRESH_BINARY)  # 将灰度图像进行二值处理,将大于等于1的索引变化为255,等于0的不变
    x_t = np.reshape(x_t, (80, 80, 1))  # 将维度转换为(80, 80, 1)
    next_state = np.append(x_t, state[:, :, :3], axis=2)  # 与上一个图片状态的前3帧图片进行串接操作
    return next_state

图片来源:http://www.lyouxi.com/ 手游