使用强化学习NatureDQN来玩打砖块

目标

打砖块是gym游戏中相对复杂一些的游戏,不同于CartPole游戏,状态空间较少,基本上10分钟左右训练就可以玩到最高分,打砖块要训练非常长的时间,因此对于更进一步去理解和优化DQN非常有帮助。

第一版尝试

打砖块的基础

打砖块的reward设置是敲打到砖块:reward = 1
5次球都未接到或者全部砖块打完了done = 1
state就是整个游戏中的全体像素
在这里插入图片描述

预处理

图片预处理

首先图片可以转为单通道,且像素只需要具体游戏区内的部分,且分辨率可以降低,因此预处理如下:

def preprocess(img):
    img_temp = img[31:195]
    img_temp = img_temp.mean(axis = 2)
    img_temp = cv2.resize(img_temp,(IMG_SIZE,IMG_SIZE))
    img_temp = (img_temp - 127.5) / 127.5
    return img_temp

状态预处理

单张图片很难表述出球运动的方向,为了更好的表现出游戏中的状态就需要连续多张图片,这里我取了连续4张图片。

网络设计

这里贴出代码,先使用三层卷积网络降维后

  def create_Q_network(self):
    # network weights
    input_layer = Input(shape=(IMG_SIZE,IMG_SIZE,4), name="unet_input")
    #converlution
    cnn1 = Convolution2D(nb_filter=32, nb_row=8, nb_col=8, border_mode='same', subsample=(4, 4))(input_layer)
    cnn1 = ReLU()(cnn1)
    cnn2 = Convolution2D(nb_filter=64, nb_row=4, nb_col=4, border_mode='same', subsample=(2, 2))(cnn1)
    cnn2 = ReLU()(cnn2)
    cnn2 = Convolution2D(nb_filter=64, nb_row=3, nb_col=3, border_mode='same', subsample=(1, 1))(cnn1)
    cnn2 = ReLU()(cnn2)
    #full connect
    fc0 = Flatten()(cnn2)
    fc1 = Dense(512)(fc0)
    #get Q_value
    q_value= Dense(self.action_dim)(fc1)
    self.model = Model(input=[input_layer], output=[q_value], name='Q_net')
    self.model.compile(loss='mse',optimizer=Adam(lr=self.learning_rate))

第二版本尝试

由于第一版读取整个图片,且需要连续4帧,在图片处理环节就需要消耗大量时间,且获得得信息其实与真正乒乓球相关得只有球得坐标以及板子的位置,且仅需要两帧就可以用于表述需要的状态,因此我改进了状态变量的,之用了4个维度。

def preprocess(img):
    img_temp = img.mean(axis = 2)
#    img_temp = cv2.resize(img_temp,(IMG_SIZE,IMG_SIZE))
    x = -1
    y = -1
    flag = 0
    if len(np.where((img_temp[100:189,8:152])!= 0)[0]) != 0:
        x = np.where((img_temp[100:189,8:152])!= 0)[0][0]
        y = np.where((img_temp[100:189,8:152])!= 0)[1][0]
    if len(np.where((img_temp[193:,8:152])!= 0)[0]) != 0:
        x = np.where((img_temp[193:,8:152])!= 0)[0][0] + 93
        y = np.where((img_temp[193:,8:152])!= 0)[1][0]
        flag = 1
#         x = -2
#         y = -2
    p = int(np.where(img_temp[191:193,8:152])[1].mean() - 7.5)
    #return img_temp
    return (x,y,p,flag)
    for step in range(STEP):
        print("episode:%d step:%d" % (episode,step))
        action = agent.egreedy_action(state_shadow)    
        next_state,reward,done,_ = env.step(action)
        (x2,y2,p2,flag) = preprocess(next_state)
        next_state_shadow = np.array([x1,y1,x2,y2,p2])
        # Define reward for agent
        #reward_agent = -1 if done else 0.1
        #加大落下的惩罚
        if flag == 1:
            reward = -10
            done = True
        else:
            reward = 0.1
        agent.perceive(state_shadow,action,reward,next_state_shadow,done)
#         if cur_loss is not None:
#             total_loss += cur_loss
        total_reward += reward
        state_shadow = next_state_shadow
        x1,y1,p1 = x2,y2,p2
        if done:
            break

经过14000 episode的迭代的效果如下:
测试出的Reward虽然整体有上升的趋势但:

  • 测试集上波动太过明显
  • 整体reward未达到期望(以我设定的step满足大于20才是比较好的效果也就是基本一个球不掉)
    在这里插入图片描述

第三版本尝试

引入prioritised,改变训练样本的权重。训练了差多15个小时左右,平均收益任然不是很理想,不过玩起来的感觉还不错了
在这里插入图片描述

代码目录:

https://github.com/hlzy/operator_dnn

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值