精华内容
下载资源
问答
  • DQN算法原理详解

    2019-05-22 21:27:00
    一、 概述 强化学习算法可以分为三大类:value based, policy based 和 actor critic。 常见的是以DQN为代表的value based算法,这种算法中只有一个值函数网络,没有...说到DQN中有值函数网络,这里简单介绍一下强...

     

    一、 概述

    强化学习算法可以分为三大类:value based, policy based 和 actor critic。

    常见的是以DQN为代表的value based算法,这种算法中只有一个值函数网络,没有policy网络,以及以DDPG,TRPO为代表的actor-critic算法,这种算法中既有值函数网络,又有policy网络。

    说到DQN中有值函数网络,这里简单介绍一下强化学习中的一个概念,叫值函数近似。一个state action pair (s,a)对应一个值函数Q(s,a)。理论上对于任意的(s,a)我们都可以由公式求出它的值函数,即用一个查询表lookup table来表示值函数。但是当state或action的个数过多时,分别去求每一个值函数会很慢。因此我们用函数近似的方式去估计值函数:^Q(s,a,w)Qπ(s,a)

    这样,对于未出现的state action也可以估计值函数。
    至于近似函数,DQN中用的是神经网络,当然如果环境比较简单的话用线性函数来近似也是可以的。

    DQN算法原文链接: 2013版(arxiv) 2015版(nature)

    二、算法原理

    强化学习是一个反复迭代的过程,每一次迭代要解决两个问题:给定一个策略求值函数,和根据值函数来更新策略。

    DQN使用神经网络来近似值函数,即神经网络的输入是state s,输出是Q(s,a),aA (action space)。通过神经网络计算出值函数后,DQN使用ϵgreedy策略来输出action(第四部分中介绍)。值函数网络与ϵgreedy策略之间的联系是这样的:首先环境会给出一个obs,智能体根据值函数网络得到关于这个obs的所有Q(s,a),然后利用ϵgreedy选择action并做出决策,环境接收到此action后会给出一个奖励Rew及下一个obs。这是一个step。此时我们根据Rew去更新值函数网络的参数。接着进入下一个step。如此循环下去,直到我们训练出了一个好的值函数网络。

    DQN-network

    那么每次迭代如何更新神经网络的参数呢?

    与机器学习类似,首先会定义一个loss function,然后使用梯度下降GD来更新参数。接下来首先介绍DQN的loss function,它与Q-Learning的非常类似,只是添加了一个target Q function。然后会介绍除此之外,DQN在Q-Learning上所做的改进。

    1、Loss Function

    L(ω)=E[(R+γmaxaQ(s,a;ω)Q(s,a;ω))2]这个公式表面上看起来很复杂,实际上很好理解,它就是一个残差模型,和我们平常见的最小二乘法很类似,真实值与预测值之间的差的平方。预测值就是Q(s,a;ω),它是神经网络的输出。“真实值”略微有一点复杂。

    想象一下假如我们想求出(s,a)的真实值函数Q(s,a)。它表示我从state s开始出发,并采取action a的话,我所能得到的整体收益的期望值。一种可能的情况是,我们知道环境的模型。这在强化学习中也叫Model Based RL。即我们知道状态转移概率矩阵:当处于(s,a)时,下一个到达的状态可能是什么,并且到达每一个状态的概率是什么;我们还知道奖励函数:当处于(s,a)时,得到的立即回报的期望值是什么;另外还知道折扣因子。由此,我们便可以通过贝尔曼方程来求解值函数。这种情况下我们可能也并不需要神经网络近似值函数之类的,直接由策略迭代或值迭代便可以求出最优策略。具体方法可以看一下MDP。

    另一种情况就是Model Free RL:不管有没有环境模型,反正我不用。那么在不知道环境模型的情况下如何求解值函数呢?答案就是采样

     

    强化学习中有多种采样的方法:

    (1) Monte Carlo

    • MC使用一个完整的episode去更新值函数,因此它需要从StSt到Terminal state的完整样本。
    • 而且需要等到episode结束才能更新值函数。
    • 由于有一条完整的样本,它可以计算出return,而值函数是return的期望,所以我们可以用return去更新值函数。

    (2) Temporal Difference / SarSa

     

    • 与MC不一样的是,TD不需要完整的样本,它只依赖下一个step的值函数,即它用V(St+1) 去更新 V(St)V(St)(TD), 或用 Q(St+1,at+1) 去更新 Q(St,at) (SarSa)
    • 它不用等到episode结束,每走一步就可以更新值函数。
    • 它不是用的真实的return值来更新值函数,而是用的一个估计值去更新另一个估计值的思想。

    另外还有TD(λ或 SarSa(λ))方法,DQN中不涉及。

     

    DQN属于Model Free的强化学习算法,它需要采样。且同SarSa类似,只依赖下一个step的值函数。但它更新值函数的方式与SarSa又有所不同。下面介绍从SarSa到Q-Learning再到DQN的更新值函数的方式。

    (1) SarSa

     

    SarSa中更新值函数的公式为:Q(s,a)Q(s,a)+α[R+γQ(s,a)Q(s,a)]也称它的target是 Rt+1+γQ(St+1,at+1)。理解这个target代表的意义:

    转载于:https://www.cnblogs.com/shona/p/10908618.html

    展开全文
  • 我们在“基础算法篇(四)值函数逼近方法解决强化学习问题”中介绍了经典的DQN算法,今天,我们就来点实际的,正式实现一下相关算法。 Tensorflow实现经典DQN算法一、基础游戏背景介绍二、建立文件与撰写主函数三、...

    我们在“基础算法篇(四)值函数逼近方法解决强化学习问题”中介绍了经典的DQN算法,今天,我们就来点实际的,正式实现一下相关算法。

    一、基础游戏背景介绍

    我们这次代码实现中,使用的对象,是Gym中的活动杆游戏,如下图所示:
    在这里插入图片描述游戏的规则非常简单,即操控黑色小车左右移动,使它上面的木棒能够保持平衡。当小车偏离中心4.8个单位,或杆的倾斜超过24度,任务失败。
    这个游戏的观测空间是一个Box(4,)对象,即四个float组成的数组;而行动空间是一个Discrete(2),即0或1。这两个值其实就决定了我们后续建立神经网络的输入和输出。
    下面,我们正式进入代码编写环节。
    备注一下:关于编程环境的搭建,请大家参考“番外篇,强化学习基础环境搭建”,本篇使用的tensorflow安装,使用pip install 命令即可,在这里不再赘述。

    二、建立文件与撰写主函数

    首先,我们可以建立一个Python文件,并按照前面我们介绍的DQN算法,写出主函数:

    env = gym.make(ENV_NAME)
    agent = DQN(env.observation_space, env.action_space)
    for episode in range(EPISODES):
        # get the initial state
        state = env.reset()
        for step in range(STEPS):
            # get the action by state
            action = agent.Choose_Action(state)
            # step the env forward and get the new state
            next_state, reward, done, info = env.step(action)
            # store the data in order to update the network in future
            agent.Store_Data(state, action, reward, next_state, done)
            if len(agent.replay_buffer) > BATCH_SIZE:
                agent.Train_Network(BATCH_SIZE)
            if step % UPDATE_STEP == 0:
                agent.Update_Target_Network()
            state = next_state
            if done:
                break
    

    我们逐行进行介绍:

    • 1.生成环境对象env
    • 2.根据观测空间和行动空间,生成agent对象 [对应(一)、(二)、(三)]
    • 3.对于每一幕游戏
    • 4.首先初始化环境,得到一个初始状态
    • 5.开始进行游戏,对于每一步
    • 6.agent根据状态得到一个行动action [对应(四)]
    • 7.将这个行动action输入环境,推动游戏向前走一步,并得到新的状态、即时奖励,以及游戏是否结束的标识
    • 8.将这一步的相关数据存入一个缓存池内 [对应(五)]
    • 9.如果缓存池内的数据量大于我们设置的进行学习的随机抽取量,则进行学习 [对应(六)]
    • 10.如果步数达到我们设置的更新频率,则更新DQN算法中目标网络的权值参数**[对应(七)]**
    • 11.最后如果这一幕游戏结束,则循环进行下一幕游戏,直到我们设计的所有幕数游戏都进行完,则结束游戏

    由上面可以看出,算法中需要重点关注的,就是由DQN类生成的agent对象,下面我们对这个对象进行详细介绍。

    三、Agent功能介绍

    本算法中的agent,就是由DQN类实例化后的对象,这个对象主要完成的功能,就是根据环境状态生成行动,同时优化网络参数,最终实现DQN算法中介绍的TD差分的最小化,下面详细介绍相关部分。

    (一)DQN类的初始化函数

    DQN 类的初始化函数主要是通过输入的状态空间和行动空间参数,生成拟合Q值的深度神经网络,并设计网络的参数更新方法,如下:

    def __init__(self, observation_space, action_space):
        # the state is the input vector of network, in this env, it has four dimensions
        self.state_dim = observation_space.shape[0]
        # the action is the output vector and it has two dimensions
        self.action_dim = action_space.n
        # init experience replay, the deque is a list that first-in & first-out
        self.replay_buffer = deque()
        # you can create the network by the two parameters
        self.create_Q_network()
        # after create the network, we can define the training methods
        self.create_updating_method()
        # set the value in choose_action
        self.epsilon = INITIAL_EPSILON
        # Init session
        self.session = tf.InteractiveSession()
        self.session.run(tf.global_variables_initializer())
    

    具体的神经网络建立方法和网络参数更新方法,我们在下面进行介绍。

    (二)建立深度神经网络

    DQN算法中设计了两个网络,current_net和target_net,两个网络结构相同,都是四层的全连接网络(state–>50–>20–>action),在后续算法中current_net用来生成行动,target_net用来计算TD目标值,具体代码如下:

    def create_Q_network(self):
        # first, set the input of networks
        self.state_input = tf.placeholder("float", [None, self.state_dim])
        # second, create the current_net
        with tf.variable_scope('current_net'):
            # first, set the network's weights
            W1 = self.weight_variable([self.state_dim, 50])
            b1 = self.bias_variable([50])
            W2 = self.weight_variable([50, 20])
            b2 = self.bias_variable([20])
            W3 = self.weight_variable([20, self.action_dim])
            b3 = self.bias_variable([self.action_dim])
            # second, set the layers
            # hidden layer one
            h_layer_one = tf.nn.relu(tf.matmul(self.state_input, W1) + b1)
            # hidden layer two
            h_layer_two = tf.nn.relu(tf.matmul(h_layer_one, W2) + b2)
            # the output of current_net
            self.Q_value = tf.matmul(h_layer_two, W3) + b3
        # third, create the current_net
        with tf.variable_scope('target_net'):
            # first, set the network's weights
            t_W1 = self.weight_variable([self.state_dim, 50])
            t_b1 = self.bias_variable([50])
            t_W2 = self.weight_variable([50, 20])
            t_b2 = self.bias_variable([20])
            t_W3 = self.weight_variable([20, self.action_dim])
            t_b3 = self.bias_variable([self.action_dim])
            # second, set the layers
            # hidden layer one
            t_h_layer_one = tf.nn.relu(tf.matmul(self.state_input, t_W1) + t_b1)
            # hidden layer two
            t_h_layer_two = tf.nn.relu(tf.matmul(t_h_layer_one, t_W2) + t_b2)
            # the output of current_net
            self.target_Q_value = tf.matmul(t_h_layer_two, t_W3) + t_b3
        # at last, solve the parameters replace problem
        # the parameters of current_net
        e_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='current_net')
        # the parameters of target_net
        t_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='target_net')
        # define the operation that replace the target_net's parameters by current_net's parameters
        with tf.variable_scope('soft_replacement'):
            self.target_replace_op = [tf.assign(t, e) for t, e in zip(t_params, e_params)]
    

    在这里我们还定义了一个拷贝网络参数的操作,self.target_replace_op,即用current_net的参数替换target_net的参数。

    (三)设计网络参数更新方法

    在DQN算法中,我们需要设置TD目标值为yjy_j,然后将(yjQ(ϕt,a;θ))2\left(y_j-Q\left(\phi_t,a;\theta\right)\right)^2作为误差,利用梯度下降法更新QQ函数的参数θ\theta。在这里我们代码实现如下:

    def create_updating_method(self):
        # this the input action, use one hot presentation
        self.action_input = tf.placeholder("float", [None, self.action_dim])
        # this the TD aim value
        self.y_input = tf.placeholder("float", [None])
        # this the action's Q_value
        Q_action = tf.reduce_sum(tf.multiply(self.Q_value, self.action_input), reduction_indices=1)
        # this is the lost
        self.cost = tf.reduce_mean(tf.square(self.y_input - Q_action))
        # use the loss to optimize the network
        self.optimizer = tf.train.AdamOptimizer(0.0001).minimize(self.cost)
    

    上面代码中:

    • self.action_input:就是我们网络输出的行为值
    • self.y_input:即上面的TD目标值yjy_j
    • Q_action:即为这个行为对应的状态行为值Q(ϕt,a;θ)Q\left(\phi_t,a;\theta\right)
    • self.cost:即为误差(yjQ(ϕt,a;θ))2\left(y_j-Q\left(\phi_t,a;\theta\right)\right)^2
    • self.optimizer:即为利用梯度下降法更新QQ函数的参数θ\theta

    (四)Agent行为生成(即利用网络输出行为)

    在DQN算法中,我们使用current_net,根据εgreedy\varepsilon-greedy方法,在状态state基础上,输出行为,代码如下所示:

    def Choose_Action(self, state):
        # the output is a tensor, so the [0] is to get the output as a list
        Q_value = self.Q_value.eval(feed_dict={
            self.state_input: [state]
        })[0]
        # use epsilon greedy to get the action
        if random.random() <= self.epsilon:
            # if lower than epsilon, give a random value
            self.epsilon -= (INITIAL_EPSILON - FINAL_EPSILON) / 10000
            return random.randint(0, self.action_dim - 1)
        else:
            # if bigger than epsilon, give the argmax value
            self.epsilon -= (INITIAL_EPSILON - FINAL_EPSILON) / 10000
            return np.argmax(Q_value)
    

    上面代码中,首先通过self.Q_value得到输出,这里需要注意的是self.Q_value的输出是一个tensor,因此,这里使用[0]来获取其输出的list。然后根据随机值进行判断,如果小于ε\varepsilon,那就随机一个行为作为输出,否则就是用argmax来输出Q_value最大值对应的索引,作为输出。

    (五)存储数据

    DQN算法中,为了实现更新,要初始化存储单元DD,存储大小为NN,并将每一步生成的{ϕt,at,rt,ϕt+1}\left\{\phi_t,a_t,r_t,\phi_{t+1}\right\}存入DD中,具体代码如下:

    def Store_Data(self, state, action, reward, next_state, done):
        # generate a list with all 0,and set the action is 1
        one_hot_action = np.zeros(self.action_dim)
        one_hot_action[action] = 1
        # store all the elements
        self.replay_buffer.append((state, one_hot_action, reward, next_state, done))
        # if the length of replay_buffer is bigger than REPLAY_SIZE
        # delete the left value, make the len is stable
        if len(self.replay_buffer) > REPLAY_SIZE:
            self.replay_buffer.popleft()
    

    上面的self.replay_buffer就是我们的存储单元DD,它是一个deque的对象,我们可以将其看作一个列表,存储方式是“先进先出”,如果大于我们设置的NN(即REPLAY_SIZE),则从左边插入新数据。

    (六)训练网络更新参数

    我们在前面设定网络参数更新方法中,已经将更新需要进行的计算公式进行了定义,那么在具体的计算中,就需要我们将数据流(flow)代入公式即可。这种使用flow的计算方式,也是我们使用的tensorflow的独特之处。具体代码如下:

    def Train_Network(self, BATCH_SIZE):
        # Step 1: obtain random minibatch from replay memory
        minibatch = random.sample(self.replay_buffer, BATCH_SIZE)
        state_batch = [data[0] for data in minibatch]
        action_batch = [data[1] for data in minibatch]
        reward_batch = [data[2] for data in minibatch]
        next_state_batch = [data[3] for data in minibatch]
    
        # Step 2: calculate TD aim value
        y_batch = []
        # give the next_state_batch flow to target_Q_value and caculate the next state's Q_value
        Q_value_batch = self.target_Q_value.eval(feed_dict={self.state_input: next_state_batch})
        # caculate the TD aim value by the formulate
        for i in range(0, BATCH_SIZE):
            done = minibatch[i][4]
            if done:
                y_batch.append(reward_batch[i])
            else:
                # the Q value caculate use the max directly
                y_batch.append(reward_batch[i] + GAMMA * np.max(Q_value_batch[i]))
    
        # step 3: update the network
        self.optimizer.run(feed_dict={
            self.y_input: y_batch,
            self.action_input: action_batch,
            self.state_input: state_batch
        })
    

    上面的训练网络主要分为三步:

    • 一是从存储单元DD中随机抽取BATCH_SIZE大小的数据;
    • 二是根据公式rj+γmaxaQ^(ϕt+1,a;θ)r_j+\gamma\cdot max_{a'}\widehat Q\left(\phi_{t+1},a';\theta^-\right)进行TD目标值yjy_j的计算;
    • 三是将相关数据流导入优化操作中,自动进行梯度下降计算,以优化current_net的参数。

    (七)更新目标网络参数

    在DQN算法中,需要每隔C步,用current_net的参数替换target_net参数,具体代码如下:

    def Update_Target_Network(self):
        # update target Q netowrk
        self.session.run(self.target_replace_op)
    

    由于我们在建立网络时,就进行了self.target_replace_op操作的定义,在这里只需要调用相关操作即可。

    总结

    以上就是经典DQN算法的实现,具体的完整代码,参见:https://github.com/samurasun/RL
    本篇中的代码参考了刘建平相关博客和代码中的内容,在这里对刘老师表示感谢。

    展开全文
  • 强化学习—DQN算法原理详解 一、 概述 强化学习算法可以分为三大类:value based, policy based 和 actor critic。常见的是以DQN为代表的value based算法,这种算法中只有一个值函数网络,没有policy网络,以及以...

    强化学习—DQN算法原理详解

    一、 概述

    强化学习算法可以分为三大类:value based, policy based 和 actor critic。常见的是以DQN为代表的value based算法,这种算法中只有一个值函数网络,没有policy网络,以及以DDPG,TRPO为代表的actor-critic算法,这种算法中既有值函数网络,又有policy网络。

    说到DQN中有值函数网络,这里简单介绍一下强化学习中的一个概念,叫值函数近似。在基本概念这篇中有讲过,一个state action pair (s,a)(s,a)对应一个值函数Q(s,a)Q(s,a)。理论上对于任意的(s,a)(s,a)我们都可以由公式求出它的值函数,即用一个查询表lookup table来表示值函数。但是当state或action的个数过多时,分别去求每一个值函数会很慢。因此我们用函数近似的方式去估计值函数:^Q(s,a,w)≈Qπ(s,a)Q^(s,a,w)≈Qπ(s,a)

    这样,对于未出现的state action也可以估计值函数。
    至于近似函数,DQN中用的是神经网络,当然如果环境比较简单的话用线性函数来近似也是可以的。

    DQN算法原文链接: 2013版(arxiv) 2015版(nature)

    二、算法原理

    基本概念中有说过,强化学习是一个反复迭代的过程,每一次迭代要解决两个问题:给定一个策略求值函数,和根据值函数来更新策略。

    上面说过DQN使用神经网络来近似值函数,即神经网络的输入是state ss,输出是Q(s,a),∀a∈AQ(s,a),∀a∈A (action space)。通过神经网络计算出值函数后,DQN使用ϵ−greedyϵ−greedy策略来输出action(第四部分中介绍)。值函数网络与ϵ−greedyϵ−greedy策略之间的联系是这样的:首先环境会给出一个obs,智能体根据值函数网络得到关于这个obs的所有Q(s,a)Q(s,a),然后利用ϵ−greedyϵ−greedy选择action并做出决策,环境接收到此action后会给出一个奖励Rew及下一个obs。这是一个step。此时我们根据Rew去更新值函数网络的参数。接着进入下一个step。如此循环下去,直到我们训练出了一个好的值函数网络。

     

    DQN-network

    那么每次迭代如何更新神经网络的参数呢?

    与机器学习类似,首先会定义一个loss function,然后使用梯度下降GD来更新参数。接下来首先介绍DQN的loss function,它与Q-Learning的非常类似,只是添加了一个target Q function。然后会介绍除此之外,DQN在Q-Learning上所做的改进。

    1、Loss Function

    L(ω)=E[(R+γ⋅maxa′Q(s′,a′;ω−)−Q(s,a;ω))2]L(ω)=E[(R+γ⋅maxa′Q(s′,a′;ω−)−Q(s,a;ω))2]这个公式表面上看起来很复杂,实际上很好理解,它就是一个残差模型,和我们平常见的最小二乘法很类似,真实值与预测值之间的差的平方。预测值就是Q(s,a;ω)Q(s,a;ω),它是神经网络的输出。“真实值”略微有一点复杂。

    想象一下假如我们想求出(s,a)(s,a)的真实值函数Q(s,a)Q(s,a)。它表示我从state ss开始出发,并采取action aa的话,我所能得到的整体收益的期望值。一种可能的情况是,我们知道环境的模型。这在强化学习中也叫Model Based RL。即我们知道状态转移概率矩阵:当处于(s,a)(s,a)时,下一个到达的状态可能是什么,并且到达每一个状态的概率是什么;我们还知道奖励函数:当处于(s,a)(s,a)时,得到的立即回报的期望值是什么;另外还知道折扣因子。由此,我们便可以通过贝尔曼方程来求解值函数。这种情况下我们可能也并不需要神经网络近似值函数之类的,直接由策略迭代或值迭代便可以求出最优策略。具体方法可以看一下MDP。

    另一种情况就是Model Free RL:不管有没有环境模型,反正我不用。那么在不知道环境模型的情况下如何求解值函数呢?答案就是采样。强化学习中有多种采样的方法,这里简单介绍一下:

    (1) Monte Carlo

     

    MC

    • MC使用一个完整的episode去更新值函数,因此它需要从StSt到Terminal state的完整样本。
    • 而且需要等到episode结束才能更新值函数。
    • 由于有一条完整的样本,它可以计算出return,而值函数是return的期望,所以我们可以用return去更新值函数。

    (2) Temporal Difference / SarSa

     

    TD

    • 与MC不一样的是,TD不需要完整的样本,它只依赖下一个step的值函数,即它用V(St+1)V(St+1) 去更新 V(St)V(St) (TD), 或用 Q(St+1,at+1)Q(St+1,at+1) 去更新 Q(St,at)Q(St,at) (SarSa)
    • 它不用等到episode结束,每走一步就可以更新值函数。
    • 它不是用的真实的return值来更新值函数,而是用的一个估计值去更新另一个估计值的思想。

    另外还有TD(λ)TD(λ) (或 SarSa(λ)SarSa(λ))方法,由于DQN中不涉及,暂不介绍。

    DQN属于Model Free的强化学习算法,它需要采样。且同SarSa类似,只依赖下一个step的值函数。但它更新值函数的方式与SarSa又有所不同。下面介绍从SarSa到Q-Learning再到DQN的更新值函数的方式。

    (1) SarSa

     

    sarsa

    SarSa中更新值函数的公式为:Q(s,a)←Q(s,a)+α[R+γQ(s′,a′)−Q(s,a)]Q(s,a)←Q(s,a)+α[R+γQ(s′,a′)−Q(s,a)]也称它的target是 Rt+1+γQ(St+1,at+1)Rt+1+γQ(St+1,at+1)。理解这个target代表的意义:V(s)=E[Gt|St=s]=E[Rt+1+γGt+1|St=s]=E[Rt+1+γV(St+1)|St=s]V(s)=E[Gt|St=s]=E[Rt+1+γGt+1|St=s]=E[Rt+1+γV(St+1)|St=s]将V换成Q的话我们可以看到,SarSa target Rt+1+γQ(St+1,at+1)Rt+1+γQ(St+1,at+1) 是 Q(St,at)Q(St,at) 的估计值。

    在值函数近似中,我们都是使用target来替代真实的值函数,即Loss中的真实值。

    前面说过DQN是使用ϵ−greedyϵ−greedy策略来输出action,SarSa和Q-Learning也是。SarSa中使用ϵ−greedyϵ−greedy策略生成action at+1at+1,随即又用 at+1at+1处对应的值函数来计算target,更新上一步的值函数。这种学习方式又称为On-policy

    SarSa属于On-policy Learning,而Q-Learning属于Off-policy Learning。

    (2) Q-Learning

     

    qlearning

    Q-Learning的target是 Rt+1+γmaxa′Q(St+1,a′)Rt+1+γmaxa′Q(St+1,a′)。它使用 ϵ−greedyϵ−greedy策略来生成action at+1at+1,但用来计算target的action却不一定是at+1at+1,而是使得 Q(St+1,a)Q(St+1,a)最大的action。这种产生行为的策略和进行评估的策略不一样的方法称为Off-policy方法。对于Q-Learning来说,产生行为的策略是ϵ−greedyϵ−greedy,而进行评估的策略是greedy。

    (3) DQN

    Off-policy是Q-Learning的特点,DQN中也延用了这一特点。而不同的是,Q-Learning中用来计算target和预测值的Q是同一个Q,也就是说使用了相同的神经网络。这样带来的一个问题就是,每次更新神经网络的时候,target也都会更新,这样会容易导致参数不收敛。回忆在有监督学习中,标签label都是固定的,不会随着参数的更新而改变。

    因此DQN在原来的Q网络的基础上又引入了一个target Q网络,即用来计算target的网络。它和Q网络结构一样,初始的权重也一样,只是Q网络每次迭代都会更新,而target Q网络是每隔一段时间才会更新。DQN的target是 Rt+1+γmaxa′Q(St+1,a′;ω−)Rt+1+γmaxa′Q(St+1,a′;ω−)。用 ω−ω−表示它比Q网络的权重 ωω更新得要慢一些。

    理解了DQN的target之后也就可以理解DQN的Loss Function了。

    2、DQN所做的改进

    相比于Q-Learning,DQN做的改进:一个是使用了卷积神经网络来逼近行为值函数,一个是使用了target Q network来更新target,还有一个是使用了经验回放Experience replay。

    由于在强化学习中,我们得到的观测数据是有序的,step by step的,用这样的数据去更新神经网络的参数会有问题。回忆在有监督学习中,数据之间都是独立的。因此DQN中使用经验回放,即用一个Memory来存储经历过的数据,每次更新参数的时候从Memory中抽取一部分的数据来用于更新,以此来打破数据间的关联。

    三、算法整体流程

    • 首先初始化Memory D,它的容量为N;
    • 初始化Q网络,随机生成权重ωω;
    • 初始化target Q网络,权重为ω−=ωω−=ω;
    • 循环遍历episode =1, 2, …, M:
    • 初始化initial state S1S1;
    • 循环遍历step =1,2,…, T:
      • 用ϵ−greedyϵ−greedy策略生成action atat:以ϵϵ概率选择一个随机的action,或选择at=maxaQ(St,a;ω)at=maxaQ(St,a;ω);
      • 执行action atat,接收reward rtrt及新的state St+1St+1;
      • 将transition样本 (St,at,rt,St+1)(St,at,rt,St+1)存入D中;
      • 从D中随机抽取一个minibatch的transitions (Sj,aj,rj,Sj+1)(Sj,aj,rj,Sj+1);
      • 令yj=rjyj=rj,如果 j+1j+1步是terminal的话,否则,令 yj=rj+γmaxa′Q(St+1,a′;ω−)yj=rj+γmaxa′Q(St+1,a′;ω−);
      • 对(yj−Q(St,aj;ω))2(yj−Q(St,aj;ω))2关于ωω使用梯度下降法进行更新;
      • 每隔C steps更新target Q网络,ω−=ωω−=ω。
    • End For;
    • End For.

    附上原文的算法流程:

    dqn

    四、ϵ−greedyϵ−greedy策略

    greedygreedy策略,顾名思义,是一种贪婪策略,它每次都选择使得值函数最大的action,即at=maxaQ(St,a;ω)at=maxaQ(St,a;ω)。但是这种方式有问题,就是对于采样中没有出现过的(state, action) 对,由于没有评估,没有Q值,之后也不会再被采到。

    其实这里涉及到了强化学习中一个非常重要的概念,叫Exploration & Exploitation,探索与利用。前者强调发掘环境中的更多信息,并不局限在已知的信息中;后者强调从已知的信息中最大化奖励。而greedygreedy策略只注重了后者,没有涉及前者。所以它并不是一个好的策略。

    而ϵ−greedyϵ−greedy策略兼具了探索与利用,它以ϵϵ的概率从所有的action中随机抽取一个,以1−ϵ1−ϵ的概率抽取at=maxaQ(St,a;ω)at=maxaQ(St,a;ω)。

    强化学习正是因为有了探索Exploration,才会常常有一些出人意表的现象,才会更加与其他机器学习不同。例如智能体在围棋游戏中走出一些人类经验之外的好棋局。

    参考资料:

    David Silver的课程:www0.cs.ucl.ac.uk/staff/D.Silver/web/Teaching.html

    展开全文
  • 上节课介绍的表格型方法存储的状态数量有限,当面对围棋或机器人控制这类有数不清的状态的环境时,表格型方法在存储和查找效率上都受局限,DQN的提出解决了这一局限,使用神经网络来近似替代Q表格。 本质上DQN还是一...

    Deep Q-Learning 算法

    Deep Q-Learning 算法简称DQN,DQN是在Q-Learning的基础上演变而来的,DQN对Q-Learning的修改主要有两个方面:

    • DQN利用深度卷积神经网络逼近值函数。
    • DQN利用了经验回放训练强化学习的学习过程。
    1. DQN简介
      上节课介绍的表格型方法存储的状态数量有限,当面对围棋或机器人控制这类有数不清的状态的环境时,表格型方法在存储和查找效率上都受局限,DQN的提出解决了这一局限,使用神经网络来近似替代Q表格。
      本质上DQN还是一个Q-learning算法,更新方式一致。为了更好的探索环境,同样的也采用ε-greedy方法训练。
      在Q-learning的基础上,DQN提出了两个技巧使得Q网络的更新迭代更稳定。
      经验回放 Experience Replay:主要解决样本关联性和利用效率的问题。使用一个经验池存储多条经验s,a,r,s’,再从中随机抽取一批数据送去训练。
      固定Q目标 Fixed-Q-Target:主要解决算法训练不稳定的问题。复制一个和原来Q网络结构一样的Target Q网络,用于计算Q目标值。

    2. DQN实践
      基于paddlepaddle的PARL,使用DQN解决CartPole问题,移动小车使得车上的摆杆倒立起来。

    Step1 安装依赖

    !pip uninstall -y parl  # 说明:AIStudio预装的parl版本太老,容易跟其他库产生兼容性冲突,建议先卸载
    !pip uninstall -y pandas scikit-learn # 提示:在AIStudio中卸载这两个库再import parl可避免warning提示,不卸载也不影响parl的使用
    
    !pip install gym
    !pip install paddlepaddle==1.6.3
    !pip install parl==1.3.1
    

    Step2 导入依赖

    import parl
    from parl import layers
    import paddle.fluid as fluid
    import copy
    import numpy as np
    import os
    import gym
    from parl.utils import logger
    

    Step3 设置超参数

    LEARN_FREQ = 5 # 训练频率,不需要每一个step都learn,攒一些新增经验后再learn,提高效率
    MEMORY_SIZE = 20000    # replay memory的大小,越大越占用内存
    MEMORY_WARMUP_SIZE = 200  # replay_memory 里需要预存一些经验数据,再开启训练
    BATCH_SIZE = 32   # 每次给agent learn的数据数量,从replay memory随机里sample一批数据出来
    LEARNING_RATE = 0.001 # 学习率
    GAMMA = 0.99 # reward 的衰减因子,一般取 0.9 到 0.999 不等
    

    Step4 搭建Model、Algorithm、Agent架构
    Agent把产生的数据传给algorithm,algorithm根据model的模型结构计算出Loss,使用SGD或者其他优化器不断的优化,PARL这种架构可以很方便的应用在各类深度强化学习问题中。
    (1)Model
    Model用来定义前向(Forward)网络,用户可以自由的定制自己的网络结构。

    class Model(parl.Model):
        def __init__(self, act_dim):
            hid1_size = 128
            hid2_size = 128
            # 3层全连接网络
            self.fc1 = layers.fc(size=hid1_size, act='relu')
            self.fc2 = layers.fc(size=hid2_size, act='relu')
            self.fc3 = layers.fc(size=act_dim, act=None)
    
        def value(self, obs):
            # 定义网络
            # 输入state,输出所有action对应的Q,[Q(s,a1), Q(s,a2), Q(s,a3)...]
            h1 = self.fc1(obs)
            h2 = self.fc2(h1)
            Q = self.fc3(h2)
            return Q
    

    (2)Algorithm
    Algorithm 定义了具体的算法来更新前向网络(Model),也就是通过定义损失函数来更新Model,和算法相关的计算都放在algorithm中。

    class DQN(parl.Algorithm):
        def __init__(self, model, act_dim=None, gamma=None, lr=None):
            """ DQN algorithm
            
            Args:
                model (parl.Model): 定义Q函数的前向网络结构
                act_dim (int): action空间的维度,即有几个action
                gamma (float): reward的衰减因子
                lr (float): learning rate 学习率.
            """
            self.model = model
            self.target_model = copy.deepcopy(model)
    
            assert isinstance(act_dim, int)
            assert isinstance(gamma, float)
            assert isinstance(lr, float)
            self.act_dim = act_dim
            self.gamma = gamma
            self.lr = lr
    
        def predict(self, obs):
            """ 使用self.model的value网络来获取 [Q(s,a1),Q(s,a2),...]
            """
            return self.model.value(obs)
    
        def learn(self, obs, action, reward, next_obs, terminal):
            """ 使用DQN算法更新self.model的value网络
            """
            # 从target_model中获取 max Q' 的值,用于计算target_Q
            next_pred_value = self.target_model.value(next_obs)
            best_v = layers.reduce_max(next_pred_value, dim=1)
            best_v.stop_gradient = True  # 阻止梯度传递
            terminal = layers.cast(terminal, dtype='float32')
            target = reward + (1.0 - terminal) * self.gamma * best_v
    
            pred_value = self.model.value(obs)  # 获取Q预测值
            # 将action转onehot向量,比如:3 => [0,0,0,1,0]
            action_onehot = layers.one_hot(action, self.act_dim)
            action_onehot = layers.cast(action_onehot, dtype='float32')
            # 下面一行是逐元素相乘,拿到action对应的 Q(s,a)
            # 比如:pred_value = [[2.3, 5.7, 1.2, 3.9, 1.4]], action_onehot = [[0,0,0,1,0]]
            #  ==> pred_action_value = [[3.9]]
            pred_action_value = layers.reduce_sum(
                layers.elementwise_mul(action_onehot, pred_value), dim=1)
    
            # 计算 Q(s,a) 与 target_Q的均方差,得到loss
            cost = layers.square_error_cost(pred_action_value, target)
            cost = layers.reduce_mean(cost)
            optimizer = fluid.optimizer.Adam(learning_rate=self.lr)  # 使用Adam优化器
            optimizer.minimize(cost)
            return cost
    
        def sync_target(self):
            """ 把 self.model 的模型参数值同步到 self.target_model
            """
            self.model.sync_weights_to(self.target_model)
    

    (3)Agent
    Agent 负责算法与环境的交互,在交互过程中把生成的数据提供给Algorithm来更新模型(Model),数据的预处理流程也一般定义在这里。

    class Agent(parl.Agent):
        def __init__(self,
                     algorithm,
                     obs_dim,
                     act_dim,
                     e_greed=0.1,
                     e_greed_decrement=0):
            assert isinstance(obs_dim, int)
            assert isinstance(act_dim, int)
            self.obs_dim = obs_dim
            self.act_dim = act_dim
            super(Agent, self).__init__(algorithm)
    
            self.global_step = 0
            self.update_target_steps = 200  # 每隔200个training steps再把model的参数复制到target_model中
    
            self.e_greed = e_greed  # 有一定概率随机选取动作,探索
            self.e_greed_decrement = e_greed_decrement  # 随着训练逐步收敛,探索的程度慢慢降低
    
        def build_program(self):
            self.pred_program = fluid.Program()
            self.learn_program = fluid.Program()
    
            with fluid.program_guard(self.pred_program):  # 搭建计算图用于 预测动作,定义输入输出变量
                obs = layers.data(
                    name='obs', shape=[self.obs_dim], dtype='float32')
                self.value = self.alg.predict(obs)
    
            with fluid.program_guard(self.learn_program):  # 搭建计算图用于 更新Q网络,定义输入输出变量
                obs = layers.data(
                    name='obs', shape=[self.obs_dim], dtype='float32')
                action = layers.data(name='act', shape=[1], dtype='int32')
                reward = layers.data(name='reward', shape=[], dtype='float32')
                next_obs = layers.data(
                    name='next_obs', shape=[self.obs_dim], dtype='float32')
                terminal = layers.data(name='terminal', shape=[], dtype='bool')
                self.cost = self.alg.learn(obs, action, reward, next_obs, terminal)
    
        def sample(self, obs):
            sample = np.random.rand()  # 产生0~1之间的小数
            if sample < self.e_greed:
                act = np.random.randint(self.act_dim)  # 探索:每个动作都有概率被选择
            else:
                act = self.predict(obs)  # 选择最优动作
            self.e_greed = max(
                0.01, self.e_greed - self.e_greed_decrement)  # 随着训练逐步收敛,探索的程度慢慢降低
            return act
    
        def predict(self, obs):  # 选择最优动作
            obs = np.expand_dims(obs, axis=0)
            pred_Q = self.fluid_executor.run(
                self.pred_program,
                feed={'obs': obs.astype('float32')},
                fetch_list=[self.value])[0]
            pred_Q = np.squeeze(pred_Q, axis=0)
            act = np.argmax(pred_Q)  # 选择Q最大的下标,即对应的动作
            return act
    
        def learn(self, obs, act, reward, next_obs, terminal):
            # 每隔200个training steps同步一次model和target_model的参数
            if self.global_step % self.update_target_steps == 0:
                self.alg.sync_target()
            self.global_step += 1
    
            act = np.expand_dims(act, -1)
            feed = {
                'obs': obs.astype('float32'),
                'act': act.astype('int32'),
                'reward': reward,
                'next_obs': next_obs.astype('float32'),
                'terminal': terminal
            }
            cost = self.fluid_executor.run(
                self.learn_program, feed=feed, fetch_list=[self.cost])[0]  # 训练一次网络
            return cost
    

    Step5 ReplayMemory
    经验池:用于存储多条经验,实现 经验回放。

    import random
    import collections
    import numpy as np
    
    class ReplayMemory(object):
        def __init__(self, max_size):
            self.buffer = collections.deque(maxlen=max_size)
    
        # 增加一条经验到经验池中
        def append(self, exp):
            self.buffer.append(exp)
    
        # 从经验池中选取N条经验出来
        def sample(self, batch_size):
            mini_batch = random.sample(self.buffer, batch_size)
            obs_batch, action_batch, reward_batch, next_obs_batch, done_batch = [], [], [], [], []
    
            for experience in mini_batch:
                s, a, r, s_p, done = experience
                obs_batch.append(s)
                action_batch.append(a)
                reward_batch.append(r)
                next_obs_batch.append(s_p)
                done_batch.append(done)
    
            return np.array(obs_batch).astype('float32'), \
                np.array(action_batch).astype('float32'), np.array(reward_batch).astype('float32'),\
                np.array(next_obs_batch).astype('float32'), np.array(done_batch).astype('float32')
    
        def __len__(self):
            return len(self.buffer)
    

    Step6 Training && Test(训练&&测试)

    # 训练一个episode
    def run_episode(env, agent, rpm):
        total_reward = 0
        obs = env.reset()
        step = 0
        while True:
            step += 1
            action = agent.sample(obs)  # 采样动作,所有动作都有概率被尝试到
            next_obs, reward, done, _ = env.step(action)
            rpm.append((obs, action, reward, next_obs, done))
    
            # train model
            if (len(rpm) > MEMORY_WARMUP_SIZE) and (step % LEARN_FREQ == 0):
                (batch_obs, batch_action, batch_reward, batch_next_obs,
                 batch_done) = rpm.sample(BATCH_SIZE)
                train_loss = agent.learn(batch_obs, batch_action, batch_reward,
                                         batch_next_obs,
                                         batch_done)  # s,a,r,s',done
    
            total_reward += reward
            obs = next_obs
            if done:
                break
        return total_reward
    
    # 评估 agent, 跑 5 个episode,总reward求平均
    def evaluate(env, agent, render=False):
        eval_reward = []
        for i in range(5):
            obs = env.reset()
            episode_reward = 0
            while True:
                action = agent.predict(obs)  # 预测动作,只选最优动作
                obs, reward, done, _ = env.step(action)
                episode_reward += reward
                if render:
                    env.render()
                if done:
                    break
            eval_reward.append(episode_reward)
        return np.mean(eval_reward)
    

    Step7 创建环境和Agent,创建经验池,启动训练,保存模型

    env = gym.make('CartPole-v0')  # CartPole-v0: 预期最后一次评估总分 > 180(最大值是200)
    action_dim = env.action_space.n  # CartPole-v0: 2
    obs_shape = env.observation_space.shape  # CartPole-v0: (4,)
    rpm = ReplayMemory(MEMORY_SIZE)  # DQN的经验回放池
    
    # 根据parl框架构建agent
    model = Model(act_dim=action_dim)
    algorithm = DQN(model, act_dim=action_dim, gamma=GAMMA, lr=LEARNING_RATE)
    agent = Agent(
        algorithm,
        obs_dim=obs_shape[0],
        act_dim=action_dim,
        e_greed=0.1,  # 有一定概率随机选取动作,探索
        e_greed_decrement=1e-6)  # 随着训练逐步收敛,探索的程度慢慢降低
    
    # 加载模型
    # save_path = './dqn_model.ckpt'
    # agent.restore(save_path)
    
    # 先往经验池里存一些数据,避免最开始训练的时候样本丰富度不够
    while len(rpm) < MEMORY_WARMUP_SIZE:
        run_episode(env, agent, rpm)
    
    max_episode = 2000
    
    # 开始训练
    episode = 0
    while episode < max_episode:  # 训练max_episode个回合,test部分不计算入episode数量
        # train part
        for i in range(0, 50):
            total_reward = run_episode(env, agent, rpm)
            episode += 1
    
        # test part
        eval_reward = evaluate(env, agent, render=False)  # render=True 查看显示效果
        logger.info('episode:{}    e_greed:{}   test_reward:{}'.format(
            episode, agent.e_greed, eval_reward))
    
    # 训练结束,保存模型
    save_path = './dqn_model.ckpt'
    agent.save(save_path)
    
    展开全文
  • 进阶阶段(一)——基本DQN算法 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也...
  • 本文主要整理和参考了李宏毅的强化学习系列课程和莫烦python的强化学习教程 ...DQN算法原理和Agent实现 Double-DQN、Dueling DQN结构原理和Agent实现 Policy Gradients算法原理和Agent实现 A2C、A3C算法原理和Age...
  • 1、算法介绍 DQN的问题有:目标 Q 值(Q Target )计算是否准确?全部通过 max  Qmax\;QmaxQ 来计算有没有问题?很显然,是有问题的,这是因为Q-Learning 本身固有的缺陷—过估计 过估计是指估计得值函数比真实值...
  • 上篇文章强化学习——状态价值函数逼近介绍了价值函数逼近(Value Function Approximation,VFA)的理论,本篇文章介绍大名鼎鼎的DQN算法DQN算法是 DeepMind 团队在2015年提出的算法,对于强化学习训练苦难问题,...
  • 在上一节中介绍的Q learnig算法利用Q table来记录和检索 Q value,在状态空间较小的情况下可以适用,但是当状态空间很大的时候,利用Q table来维护数据就不太可行了,所以就诞生了deep Q network(DQN算法,也叫...
  • python_强化学习算法DQN_玩五子棋游戏

    千次阅读 多人点赞 2021-03-14 14:24:54
    一个基于CNN构成的DQN算法的8*8的五子棋游戏 1、Q-Learning介绍 Q-Learning的思想并不是很复杂,很多文章都有详细的介绍,这里只是简单举个例子,不做详细讲解。 如何用简单例子讲解 Q - learning 的具体过程? 2、...
  • 进阶阶段(一)DQN算法入门 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越...
  • 项目实战:使用Deep Q Network(DQN算法让机器学习玩游戏(一):总体介绍,游戏部分 项目实战:使用Deep Q Network(DQN算法让机器学习玩游戏(二):算法部分 项目实战:使用Deep Q Network(DQN算法让...
  • 项目实战:使用Deep Q Network(DQN算法让机器学习玩游戏(一):总体介绍,游戏部分 项目实战:使用Deep Q Network(DQN算法让机器学习玩游戏(二):算法部分 项目实战:使用Deep Q Network(DQN算法让...
  • 项目实战:使用Deep Q Network(DQN算法让机器学习玩游戏(一):总体介绍,游戏部分 项目实战:使用Deep Q Network(DQN算法让机器学习玩游戏(二):算法部分 项目实战:使用Deep Q Network(DQN算法让...
  • 本文主要介绍DQN算法的基本原理,以及在它基础上改进的DDQN和Dueling DQN,介绍完后会结合对应的PARL代码进行解析说明(PARL 是一个高性能、灵活的强化学习框架)。 三篇相关的论文地址如下,接下去的三个小节会围绕...
  • Nature DQN与Double DQN

    2020-02-03 09:08:00
    在前面的文章强化学习DQN算法中,介绍了经典的DQN算法,然而DQN也存在一些问题。Nature DQN与Double DQN的提出就是为了解决这些问题,下面笔者将介绍这个两种改进的算法...
  • 本篇文章内容涉及DQN算法介绍以及利用DQN解决MountainCar。 强化学习 强化学习的目标是学习到策略,使得累计回报的期望值最大,即:            为了便于求解最优策略,引入值函数和动作状态值函数来评价...
  • 在前面的文章Nature DQN与Double DQN中介绍了对DQN算法的两种改进,Nature DQN加快了收敛速度,Double DQN有效的解决了过拟合的现象,本篇文章将继续介绍...
  • (零基础可以看懂)深度强化学习之DQN算法之第2篇-2015年Nature版本的DQN(含代码)-《强化学习系列专栏第5篇》背景论文原文链接介绍模型关键部分解释代码跑的结果展示代码代码复现、详细讲解及我的Github地址 ...
  • (零基础可以看懂)深度强化学习之DQN算法-第1篇(含代码)-《强化学习系列专栏第4篇》背景论文原文链接介绍模型关键部分解释代码代码复现、详细讲解及我的Github地址 背景     DQN是由Deep Q-Learning缩写而...
  • 【RL】DQN及其各种优化算法

    千次阅读 2020-02-10 00:40:31
    上一篇博文的末尾,我们介绍了传统QLearning的劣势——那就是需要维护一个Q表,而对于很多状态,连续动作的情况,我们Q表的大小将会爆炸性地增长。我们微小的内存必然存不下这么大的Q表。所以我们要转换我们的思路。...
  • 强化学习算法介绍

    2021-06-01 14:59:43
    强化学习算法介绍 对比学习一: sarsa Q-learning DQN policy gradient DDPG Actor-Critic Soft Actor-Critic A3C PPO 离散:DQN 连续:DDPG
  • 强化学习算法 DQN 解决 CartPole 问题,移动小车使得车上的摆杆保持直立。 这个游戏环境可以说是强化学习中的 “Hello World” 大部分的算法都可以先利用这个环境来测试下是否可以收敛 环境介绍: 小车在一个...
  • DQN算法是在Q-learning基础上的改进,在Q-learning中必须存在一张Q表。当时当环境变得极其复杂时,Q表的数据量会相当大,更新过程会变得异常复杂。在经过深度网络的学习之后,我们就可以利用神经网络来代替Q表,只...
  • 这是新开的一个系列,将结合理论和部分代码(by ElegantRL)介绍强化学习中的算法,将从基础理论总结到现在常用的SAC,TD3等算法,希望能帮助大家重温知识点。本文是第一部分,将从基础理论讲解到DQN的各种变体。 ...
  • 最近学习DQN算法绕了很多弯子,踩了很多坑,这里梳理一下,一来给自己学习过程留个记录,二来趁着坑比较热乎,写出来给大家分享分享。 代码中有居于ANN的九宫格游戏 已经训练好的 还有一个基于CNN...
  • 本篇介绍三种DQN的变体,分别是从参数更新部分改进的Double DQN,从经验回放部分改进的Prioritized DQN,从神经网络结构部分改进的Dueling DQN。 Double DQN 上一篇提到的DQN是基于Q-learning,更新也是基于贪婪...
  • 微软开源了基于虚幻4引擎的一款用于模拟无人机...非常适合做视觉算法的测试以及仿真环境的训练等等,下面介绍如何快速使用次仿真环境完成project的运行和使用。 首先是要虚幻4引擎和airsim的安装,两篇讲得比较好的 ...
  • 本论文不仅重点标注了实现过程中的终止条件和优化算法等关键点,同时还讨论了实现的性能改进方案。机器之心简要介绍了该论文,更详细的实现细节请查看原论文。 过去几年来,深度强化学习逐渐流行,因为它在有...
  • Double DQN——解决DQN中的过估计问题

    千次阅读 2019-07-23 09:35:56
    本篇教程是基于Deep Q network(DQN)的教程,缩减了在DQN方面的介绍,着重强调Double DQNDQN的不同之处。 接下来我们说说为什么会有Double DQN这种算法,所以我们从Double DQN相对于Natural DQN(传统DQN)的优势...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 125
精华内容 50
关键字:

dqn算法介绍