dqn在训练过程中loss越来越大_用DQN算法玩FlappyBird

本文介绍了如何运用DQN算法解决FlappyBird的离散动作问题。通过提取关键状态信息,如小鸟速度、与水管的距离,实现游戏状态的简化。在训练过程中,通过封装游戏环境并实现Double-Q Learning,利用tensorboard监控训练进度。随着训练进行,算法表现逐步提升,完成步骤数增加,loss逐渐稳定。
摘要由CSDN通过智能技术生成

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值