强化学习---DQN相关知识及代码实现

DQN全名为Deep Q-Network,是结合了Q-learning和深度学习网络的一个网络结构模型。

接下来分析DQN的实现流程及细节处理:

 

一:为什么提出DQN:

Q-learning作为传统的强化学习算法,功能强大且好实现,但存在一个致命的弱点,便是,Q-learning需要一个状态转移表,来保存状态及决定下一步的action,但当状态很多时,且可采取的行动较多时,这个表格便会变得异常庞大,且不好维护,不好拟合训练。比如FlappyBird游戏中,训练Bird自动飞行,因为管道跟bird的位置不定,所以存在的状态将会很多。

所以便结合深度学习,使用网络结构,将当前的画面信息作为net的输入,将下一步action作为net的输出,通过计算loss反向传递训练网络。

 

二:网络构建及数据准备

(1).DQN有两个结构相同的网络,分别为eval_net跟target_net,两个网络结构相同,参数可以互相替换,eval_net是用于训练的网络,为了输出评估值,记作y_eval,target_net是用于输出目标值,记作y_target,在间隔一定迭代训练次数,便将eval_net网络的参数复制给target_net,网络训练loss计算便是y_eval-y_target。

(2).将当前环境信息s输入eval_net,输出Q值,选取对应的action,或者随机生成action(记为a0,执行action,获取得到对应的reward(记为r)及对应新的环境信息s_,整合信息,将样本(s,a,r,s_)存储起来,例如存进队列Queue,并迭代,保存最近一定量的信息。

 

三:训练过程:

(1):随机提取一个batch的sample(s,a,r,s_),将s输入eval_net,得到输出,记为q_eval,根据sample中的a值,保留q_eval对应位置的q值,其它位置q值置为0,记作y_eval。

(2):将sample中的s_输入到target_net,得到输出,记为q_target,保留q_target中最大值位置的值,其它位置置为0,并乘以系数gamma,然后加上sample对应的r,结果记为y_target。

(3):计算y_eval与y_target的MSE(均方误差),作为loss方向传递,调整eval_net。

(4):判断是否将eval_net里面的参数复制给target_net。

(5):重复步骤1到步骤4。

流程图如下:

 

伪代码如下:

sampleQueue = Queue()
timeStep = 0

#构建网络结构net_eval,net_target
EvalNet = createNet(stateInput)
TargetNet = createNet(stateInputT)

#构建loss函数及优化器
loss = tf.reduce_mean(tf.square(y_eval - y_target))
trainStep = tf.train.AdamOptimizer(1e-6).minimize(loss)
   
#开始游戏保留初始状态
observation0, reward0 = playGame(action0)
currentState= preprocess(observation0)

#根据当前状态获取下一步action,分别可以随机获取action,或通过EvalNet网络获取。
def getAction(currentState):
    if random.random > epsilon:
        action = randomGet()
    else:
        action = EvalNet(currentState) 
    return action
    
while 1!= 0:
    #执行action并保存sample
    action = getAction(currentState)
    nextObservation,reward = playGame(action)
    newState= preprocess(nextObservation)
    sampleQueue.append((currentState,action,reward,newState))
    
    #当smaple数量达到上限,便剔除最久之前的sample
    if len(sampleQueue) > MEMORY_MAX:
        sampleQueue.pop(0)
    #达到一定sample数目便开始训练网络
    if timeStep > OBSERVE:
        trainData= random.sample(replayMemory,BATCH_SIZE)
        trainData_state = trainData[:,0]
        trainData_action = trainData[:,1]
        trainData_reward = trainData[:,2]
        trainData_nextState = trainData[:,3]
        
        q_target = TargetNet(trainData_nextState)
        y_target = trainData_reward + GAMMA*max(q_target)
        
        #根据y_target,trainData_state(将trainData_state输入EvalNet可得到y_eval),trainData_action可计算loss并训练网络EvalNet
        trainStep.run()

        #间隔一定次数,便将EvalNet参数赋值给TargetNet
        if timeStep % UPDATE_TIME == 0:
            copyEvalNetToTargetNet()

    currentState = newState
    timeStep += 1

 

四:实验细节

(1).是否action需要进行随机获取,如果action都是将当前环境输入EvalNet,通过输出值决定下一步action,那么前期训练时,EvalNet容易过拟合,一直输出执行某个操作,所以随机获取,可以增多sample的多样性,更容易训练网络,训练后期可放弃随机获取的方式。

(2).是否需要TargetNet网络,直接使用EvalNet获取y_target,经实验,如若这样做,EvalNet同样可拟合,同样可训练出相应的模型,但前期训练时,较难拟合,模型振荡较大,迭代次数较多。

(3).Net的输入可使用当前的环境状态,也可使用当前的环境状态,并combine前几帧的环境状态,即前几个状态,作为整体,输入Net进行训练,经试验,效果相差不大,但按理说,如若combine前几帧的环境状态,Net网络会参照之前的状态,再决定action,效果会更优,但模型的输入变大,计算量也会相应提高。

(4).Gamma系数一般取接近1的值较为合理。

 

参照资料

(1):https://blog.csdn.net/weixin_39721214/article/details/90070881

(2):https://github.com/floodsung/DRL-FlappyBird

(3):https://blog.csdn.net/xckkcxxck/article/details/83744057

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿也可以很哲学

让我尝下打赏的味道吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值