赞
踩
DQN全名为Deep Q-Network,是结合了Q-learning和深度学习网络的一个网络结构模型。
接下来分析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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。