DQN算法的原理与复现

基本思路

先来解释下Q-learning
简单来说就是瞬时奖励+记忆经验奖励。

瞬时奖励:做了一个动作就能获得的奖励

经验奖励:按照训练时的经验,上一系列动作发生之后,接下来怎么做才能获得更大的奖励,换句话就是说根据复盘经验去研究如何更好地补刀,从而形成一系列的动作(连招)

DQN自然就是加入深度神经网络进行预测,我们先来看看Q-learning是如何运行的

1收集数据(即游戏记录)

DQN算法的原理与复现
2令目标等于以下公式(获得价值最高的选择):
DQN算法的原理与复现
3目标函数(获得最小的误差)
DQN算法的原理与复现

整体流程

DQN算法的原理与复现
伽马值(就是那个很像r的)用于减少下一步的贡献度,因为下一步与上一步紧密相连,故不能减少太多,我们也是将其设置为0.99
DQN算法的原理与复现
因为其是瞬时奖励,加的是记忆中价值量最大的动作,但也终归是记忆中的,我们要对其影响做一个削弱,构成一个估计值

举个通俗的例子,走迷宫
状态0,1,2,3,4,5,其中5是出口
目标就是能走出去
并非每个状态都是互通的(比如2到3)
通过不断地迭代让智能体逃出去

DQN算法的原理与复现
5是出口我们就直接把运行到状态5的奖励设为100,其余为0
DQN算法的原理与复现
数据的格式
对R与Q进行初始化
Q是一个由0构成的没有实际意义的空表,要不断地进行填充
行为state,列为action
DQN算法的原理与复现
-1表示此路不通,只要没到5,奖励都为0

开始迭代
假设初始化状态为1
根据右表action只能选择3和5
此时选择3还是5呢,当前的Q为空表,按理来说是要比较这两个选择的价值的,但是我们是从0开始训练,故我们只能先随机选一个,比如5
接下来就到了状态5,此时有三种选择,1,4,5,选哪个呢

DQN算法的原理与复现
DQN算法的原理与复现
其中0.8是伽马值,就是折扣因子,相当于经验记忆奖励的权重,然后由此我们就得到了Q(1,5),5亦代表了游戏结束
如此重复,尽可能地把每个可能性都试一遍,这也是为什么次数越多模型的准确度越高的原因,联想一波蒙特卡洛即可。

那么我们想一下,如果放到游戏画面,我们真的能做到穷举吗,那个像素点太多了,Q(s,a)就不能用表格来表达了,于是我们想到了用神经网络去表达,现在一般的方法是构建一个 replay buffers 到时候去里面取一个batch就行,其实就是off policy策略,这个策略的代码构建还是比较容易的,

DQN算法的原理与复现
对DQN的改进
DQN算法的原理与复现
DQN算法的原理与复现

第一种改进,double-dqn

DQN算法的原理与复现
红色为目标,蓝色为模型达到的程度
换句话说就是模型高估了自己
DQN算法的原理与复现

为了提升模型效果,我们在原来训练的基础上再用另一个神经网络训练一次

DQN算法的原理与复现

注意,里面的括号下方的小A与小B都代表一个神经网络

第二种改进,dueling-dqn

在同一个网络中分别嫁接两个全连接层,以此为原理使得网络能同时更新相同state下不同的行为(action)可能导致的结果

DQN算法的原理与复现

DQN算法的原理与复现
也就是说其实只有V(s)是变量用于微调

mulit-step-dqn策略
就像下围棋一样,
不光要看眼前的下一步,也要看下N步的结果,该算法就是在计算Q值得时候选择多个时间步

只看下一步

DQN算法的原理与复现
只看下N步
DQN算法的原理与复现
联想下梯度下降中的随机/批量,这个就是小批量

连续值的处理方法-连续动作

DQN算法的原理与复现
这就是一个求极值的问题,常用的解法有采样,梯度上升
不断地运行,并比较,选择一个最大值就可以了
DQN算法的原理与复现
问题来了,这样子不断地运算,动作越多计算的负担越大,于是我们要优化计算方法,改变数据的输入格式
DQN算法的原理与复现
即重新定义Q网络,输出三个结果分别是向量,矩阵,值

由此构成新的公式

DQN算法的原理与复现
DQN算法的原理与复现
这个是恒为正的,
DQN算法的原理与复现
此时代入Q(s,a)即可得出
DQN算法的原理与复现

; 部分代码复现

训练网络

while True:

    env.render()
    action = RL.choose_action(observation)
    observation_,reward,done = env.step(action)
    RL.store_transition(observation,action,reward,observation_)
    if (step>x) and (step%y== 0):
        RL.learn()
        observation = observation_
    if done:
        break
    step += 1

DQN算法的原理与复现

行动参数更新


def choose_action(self,observation):
    observation = observation[np.newaxis,:]
    if np.random.uniform() < self.epsilon:
        actions_value = self.sess.run(self.q_eval,feed_dict = {self.s:observation})
        action = np.argmax(actions_value)
    else:
        action = np.random.randint(0,self.n_actions)
    return action

经验池


def store_transition(self,s,a,r,s_):

    if not hasattr(self,'memory_counter'):
        self.memory_counter = 0
        transition = np.hstack(s,[a,r],s_)
        index = self.memory_counter%self.memory_size
        self.memory[index,:] = transition
        self.memory_counter += 1

学习函数


def leran(self):
    q_traget = q_eval.copy()
    batch_index = np.arange(self.batch_size,dtype = np.int32)
    eval_act_index = batch_memory[:,self.n_fextures].astype(int)
    reward = batch_memory[;self.n_fextures +1]
    q_traget[batch_index,eval_act_index] = reward + self.gamma * np.max(q_next,axis = 1)
    -,self.cost = self.sess.run([self._train_op,self.loss],feed_dict = {self.s:batch_memory[:,:self.n_fextures],self.q_traget:q_traget})
    self.cost_his.append(self.cost)

网络搭建

def _build_net(self):

        self.s = tf.placeholder(tf.float32, [None, self.n_features], name='s')
        self.q_target = tf.placeholder(tf.float32, [None, self.n_actions], name='Q_target')
        with tf.variable_scope('eval_net'):

            c_names, n_l1, w_initializer, b_initializer = \
                ['eval_net_params', tf.GraphKeys.GLOBAL_VARIABLES], 10, \
                tf.random_normal_initializer(0., 0.3), tf.constant_initializer(0.1)

            with tf.variable_scope('l1'):
                w1 = tf.get_variable('w1', [self.n_features, n_l1], initializer=w_initializer, collections=c_names)
                b1 = tf.get_variable('b1', [1, n_l1], initializer=b_initializer, collections=c_names)
                l1 = tf.nn.relu(tf.matmul(self.s, w1) + b1)

            with tf.variable_scope('l2'):
                w2 = tf.get_variable('w2', [n_l1, self.n_actions], initializer=w_initializer, collections=c_names)
                b2 = tf.get_variable('b2', [1, self.n_actions], initializer=b_initializer, collections=c_names)
                self.q_eval = tf.matmul(l1, w2) + b2

        with tf.variable_scope('loss'):
            self.loss = tf.reduce_mean(tf.squared_difference(self.q_target, self.q_eval))
        with tf.variable_scope('train'):
            self._train_op = tf.train.RMSPropOptimizer(self.lr).minimize(self.loss)

        self.s_ = tf.placeholder(tf.float32, [None, self.n_features], name='s_')
        with tf.variable_scope('target_net'):

            c_names = ['target_net_params', tf.GraphKeys.GLOBAL_VARIABLES]

            with tf.variable_scope('l1'):
                w1 = tf.get_variable('w1', [self.n_features, n_l1], initializer=w_initializer, collections=c_names)
                b1 = tf.get_variable('b1', [1, n_l1], initializer=b_initializer, collections=c_names)
                l1 = tf.nn.relu(tf.matmul(self.s_, w1) + b1)

            with tf.variable_scope('l2'):
                w2 = tf.get_variable('w2', [n_l1, self.n_actions], initializer=w_initializer, collections=c_names)
                b2 = tf.get_variable('b2', [1, self.n_actions], initializer=b_initializer, collections=c_names)
                self.q_next = tf.matmul(l1, w2) + b2

Original: https://blog.csdn.net/CSDNXXCQ/article/details/117354917
Author: 丰。。
Title: DQN算法的原理与复现

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/623057/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球