dqn在训练过程中loss越来越大_用DQN算法玩FlappyBird
发布日期:2021-06-24 17:45:34 浏览次数:2 分类:技术文章

本文共 2819 字,大约阅读时间需要 9 分钟。

DQN算法可以用于解决离散的动作问题,而FlappyBird的操作正好是离散的。

FlappyBird的游戏状态一般可以通过图像加卷积神经网络(CNN)来进行强化学习。但是通过图像分析会比较麻烦,因为每次只输入一帧图像可能是不够的,因为一帧的图像分析不出小鸟的速度信息,所以通常需要几帧图像一起送入CNN分析。这样的方法麻烦又复杂,仔细观察一下游戏。

3421a67fada81bfe28175590174eb103.gif
FlappyBird游戏

发现有三个信息对于小鸟能够顺利飞过水管比较重要:

  1. 小鸟的水平速度。
  2. 小鸟与它前面一对水管中下面那根水管的水平距离。
  3. 小鸟与它前面一对水管中下面那根水管的顶端的垂直距离。

而其他的信息,比如:已经飞过了的水管等信息就不重要了。

好了,思路已经有了,开始准备环境。

一、安装FlappyBird

ntasfi/PyGame-Learning-Environment​github.com
9a42f967873d1f5995aca4d58bd98e91.png

提供了一个FlappyBird游戏的实现,按照着文档中Installation部分的提示安装就可以了。安装完了后还不能直接使用,原因如下:

  1. 需要根据游戏的状态提取上面提到的那三个重要的状态信息。
  2. 封装成和gym环境类似的接口,使用起来也方便一下。

封装好后的核心代码及注释如下:

def _get_obs(self):        # 获取游戏的状态        state = self.game.getGameState()        # 小鸟与它前面一对水管中下面那根水管的水平距离        dist_to_pipe_horz = state["next_pipe_dist_to_player"]        # 小鸟与它前面一对水管中下面那根水管的顶端的垂直距离        dist_to_pipe_bottom = state["player_y"] - state["next_pipe_top_y"]        # 获取小鸟的水平速度        velocity = state['player_vel']        # 将这些信息封装成一个数据返回        return np.array([dist_to_pipe_horz, dist_to_pipe_bottom, velocity])

完整FlappyBird状态获取封装的代码在:

flappybird_wrapper.py​github.com

二、实现DQN算法

因为最终实现的代码比较长,这里只贴算法实现中最核心的learn代码及注释:

def learn(self, writer):        # 根据经验进行学习        # 确保经验池里的经验以及足够多时,才进行学习        assert WARMUP_SIZE >= BATCH_SIZE        if len(self.memory) < WARMUP_SIZE:            return        # 从经验池中选取BATCH_SIZE条经验出来        batch = random.sample(self.memory, BATCH_SIZE)        batch = Transition(*(zip(*batch)))        # 把这些经验都转换位Tensor        s0 = torch.FloatTensor(batch.state).to(device)        a0 = torch.LongTensor(batch.action).to(device).unsqueeze(1)        r1 = torch.FloatTensor(batch.reward).to(device)        s1 = torch.FloatTensor(batch.next_state).to(device)        d1 = torch.LongTensor(batch.done).to(device)        # DQN算法        q_pred = self.model(s0).gather(1, a0).squeeze()        with torch.no_grad():            if USE_DBQN:                acts = self.model(s1).max(1)[1].unsqueeze(1)                q_target = self.target_model(s1).gather(1, acts).squeeze(1)            else:                q_target = self.target_model(s1).max(1)[0]            q_target = r1 + GAMMA * (1 - d1) * q_target        loss = self.loss_func(q_pred, q_target)        self.optimizer.zero_grad()        loss.backward()        self.optimizer.step()        # 记录每次学习的loss        writer.add_scalar('train/value_loss', loss.item(), self.update_count)        self.update_count += 1        # 每MODEL_SYNC_COUNT同步一下目标模型        if self.update_count % MODEL_SYNC_COUNT == 0:            self.target_model.load_state_dict(self.model.state_dict())

在这段代码中,可以通过设置变量USE_DBQN为true和false来控制是否使用DQN的变种算法Double-Q Learning来训练模型。同时,代码还借助tensorboard来记录在训练过程中:完成步骤数(finish_step)、每局获得奖励的总数(total_reward)以及每次学习时loss的值(value_loss)来观察训练的过程。

d3c68e8059977eba98c7de07a709ab27.png
DQN训练FlappyBird的过程

从tensorboard的截图中可以看出,随着训练的进行,每局游戏结束时的步骤数finish_step)越来越多,表明算法在正确的进行训练和提高。

最后,所有的代码都可以在github中查看(包括tensorboard的记录数据):

dqn_flappybird​github.com

转载地址:https://blog.csdn.net/weixin_34214135/article/details/113067587 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:mysql --initalize_MySQL初始化设置
下一篇:db2top详细使用方法_Py之PIL:Python的PIL库的简介、安装、使用方法详细攻略

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月15日 01时34分04秒