人工智能作为当前热门在我们生活中得到了广泛应用,尤其是在智能游戏方面,有的已经达到了可以和职业选手匹敌的效果。而DQN算法作为智能游戏的经典选择算法,其主要是通过奖励惩罚机制来迭代模型,来达到更接近于人类学习的效果。
那在强化学习中, 神经网络是如何被训练的呢? 首先, 我们需要 a1, a2 正确的Q值, 这个 Q 值我们就用之前在 Q learning 中的 Q 现实来代替. 同样我们还需要一个Q估计来实现神经网络的更新. 所以神经网络的的参数就是老的NN参数加学习率 alpha乘以Q现实和Q估计的差距。
我们通过 NN 预测出Q(s2, a1) 和 Q(s2,a2) 的值, 这就是 Q 估计. 然后我们选取 Q 估计中最大值的动作来换取环境中的奖励 reward. 而 Q 现实中也包含从神经网络分析出来的两个 Q 估计值, 不过这个 Q 估计是针对于下一步在 s’ 的估计. 最后再通过刚刚所说的算法更新神经网络中的参数.
DQN是第一个将深度学习模型与强化学习结合在一起从而成功地直接从高维的输入学习控制策略。
- 创新点:
基于Q-Learning构造Loss Function(不算很新,过往使用线性和非线性函数拟合Q-Table时就是这样做)。
通过experience replay(经验池)解决相关性及非静态分布问题;
使用TargetNet解决稳定性问题。
- 优点:
算法通用性,可玩不同游戏;
End-to-End 训练方式;
可生产大量样本供监督学习。
- 缺点:
无法应用于连续动作控制;
只能处理只需短时记忆问题,无法处理需长时记忆问题(后续研究提出了使用LSTM等改进方法);
CNN不一定收敛,需精良调参。
整体的程序效果如下:
实验前的准备
首先我们使用的python版本是3.6.5所用到的库有cv2库用来图像处理;
Numpy库用来矩阵运算;TensorFlow框架用来训练和加载模型。Collection库用于高性能的数据结构。
程序的搭建
1、游戏结构设定:
我们在DQN训练前需要有自己设定好的程序,即在这里为弹珠游戏。在游戏整体框架搭建完成后,对于计算机的决策方式我们需要给他一个初始化的决策算法为了达到更快的训练效果。
程序结构的部分代码如下:
def __init__(self): self.__initGame() # 初始化一些变量 self.loseReward = -1 self.winReward = 1 self.hitReward = 0 self.paddleSpeed = 15 self.ballSpeed = (7, 7) self.paddle_1_score = 0 self.paddle_2_score = 0 self.paddle_1_speed = 0. self.paddle_2_speed = 0. self.__reset() ''' 更新一帧 action: [keep, up, down] ''' # 更新ball的位置 self.ball_pos = self.ball_pos[0] + self.ballSpeed[0], self.ball_pos[1] + self.ballSpeed[1] # 获取当前场景(只取左半边) image = pygame.surfarray.array3d(pygame.display.get_surface()) # image = image[321:, :] pygame.display.update() terminal = False if max(self.paddle_1_score, self.paddle_2_score) >= 20: self.paddle_1_score = 0 self.paddle_2_score = 0 terminal = True return image, reward, terminal def update_frame(self, action): assert len(action) == 3 pygame.event.pump() reward = 0 # 绑定一些对象 self.score1Render = self.font.render(str(self.paddle_1_score), True, (255, 255, 255)) self.score2Render = self.font.render(str(self.paddle_2_score), True, (255, 255, 255)) self.screen.blit(self.background, (0, 0)) pygame.draw.rect(self.screen, (255, 255, 255), pygame.Rect((5, 5), (630, 470)), 2) pygame.draw.aaline(self.screen, (255, 255, 255),