[强化学习笔记专题(二)]Nature DQN

2023-05-16

转自 我的博客

DQN (Nature)

1

一、 算法流程:

  1. 定义可配置参数
    • episode 数量 M
    • 最大仿真时间 T, ϵ − g r e e d y \epsilon-greedy ϵgreedy参数 ϵ l o w \epsilon_{low} ϵlow, ϵ h i g h \epsilon_{high} ϵhigh
    • batch size N ​ N​ N
    • 折扣率 γ \gamma γ,学习率 α \alpha α等优化器参数
    • Soft update 频率 C ​ C​ C
  2. 初始化
    • 初始化 replay buffer 大小N
    • 初始化 Q 网络 Q ​ Q​ Q ,使用随机权值 θ ​ \theta​ θ
    • 初始化 TargetQ 网络 Q ^ \hat{Q} Q^ 权值 θ − \theta^- θ,使用 Q 网络的权值 θ \theta θ
  3. DQN 一个Episode的流程
    • 使用 ϵ − g r e e d y \epsilon-greedy ϵgreedy 策略 选择一个 action a t a_t at
    • 执行当前 action a t a_t at, 获取下一个状态 s t + 1 s_{t+1} st+1 和 reward r t r_{t} rt
    • 将当前状态 s t s_t st赋值为下一个状态 s t + 1 s_{t+1} st+1
    • 将五元组$\langle s_t,a_t,r_t,s_{t+1},done \rangle $存入 replay buffer D D D
    • 训练Q网络 Q ​ Q​ Q:
      • **[Pre-condition]**训练网络的前提是 **replay buffer 的已有五元组数量大于 batch size ** N N N
      • 从 replay buffer D ​ D​ D中随机选取 batch size N ​ N​ N条数据 ⟨ s j , a j , r j , s j + 1 , d o n e ⟩ ​ \langle s_j,a_j,r_j,s_{j+1},done\rangle​ sj,aj,rj,sj+1,done D s e l e c t e d ​ D_{selected}​ Dselected
      • 计算目标Q值 y ​ y​ y y ​ y​ y是一个向量, { y j ∈ y ∣ j ∈ [ 0 , N ] } ​ \{y_j \in y |j\in[0,N]\} ​ {yjyj[0,N]},大小为 batch size N ​ N​ N
        • D s e l e c t e d ​ D_{selected}​ Dselected[j] 中 d o n e = T r u e ​ done=True​ done=True 时,即终局状态,此时 y j = r j ​ y_j=r_j​ yj=rj
        • D s e l e c t e d D_{selected} Dselected[j] 中 d o n e = F a l s e done=False done=False 时,即非终局状态,此时 y i = r j + γ m a x a ′ Q ^ ( s j + 1 , a ′ ; θ − ) y_i=r_j+\gamma max_{a'}\hat{Q}(s_{j+1},a';\theta^-) yi=rj+γmaxaQ^(sj+1,a;θ), 注意这里是用的 TargetQ 网络进行的
      • 使用优化器进行梯度下降,损失函数是(一个batch里面) ( y − Q ( s , a ; θ ) ) 2 ​ (y-Q(s,a;\theta))^2​ (yQ(s,a;θ))2,注意这里使用的是Q网络进行,来让计算出来的目标Q值当前Q网络输出的Q值进行MSE
      • C C C 次 episode,soft update 一次 target net 参数, θ − = θ \theta^- = \theta θ=θ
  4. 不断迭代Episode流程 M M M

img

二、对应代码

完整代码地址: Nature DQN

  1. 初始化
    • 初始化 replay buffer 大小N
    • 初始化 Q 网络 Q Q Q ,使用随机权值 θ \theta θ
    • 初始化 TargetQ 网络 Q ^ \hat{Q} Q^ 权值 θ − \theta^- θ,使用 Q 网络的权值 θ \theta θ
        def create_Q_network(self):
            """
            Q net 网络定义
            :return:
            """
            # 输入状态 placeholder
            self.state_input = tf.placeholder("float", [None, self.state_dim])
    
            # Q 网络结构 两层全连接
            with tf.variable_scope('current_net'):
                W1 = self.weight_variable([self.state_dim, 100])
                b1 = self.bias_variable([100])
                W2 = self.weight_variable([100, self.action_dim])
                b2 = self.bias_variable([self.action_dim])
                h_layer = tf.nn.relu(tf.matmul(self.state_input, W1) + b1)
                # Q Value
                self.Q_value = tf.matmul(h_layer, W2) + b2
    
            # Target Net 结构与 Q相同,可以用tf的reuse实现
            with tf.variable_scope('target_net'):
                W1t = self.weight_variable([self.state_dim, 100])
                b1t = self.bias_variable([100])
                W2t = self.weight_variable([100, self.action_dim])
                b2t = self.bias_variable([self.action_dim])
                h_layer_t = tf.nn.relu(tf.matmul(self.state_input, W1t) + b1t)
                # target Q Value
                self.target_Q_value = tf.matmul(h_layer_t, W2t) + b2t
    
            t_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='target_net')
            e_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='current_net')
    
            # soft update 更新 target net
            with tf.variable_scope('soft_replacement'):
                self.target_replace_op = [tf.assign(t, e) for t, e in zip(t_params, e_params)]
    
    #===============================================================#
        def weight_variable(self, shape):
            """
            初始化网络权值(随机, truncated_normal)
            :param shape:
            :return:
            """
            initial = tf.truncated_normal(shape)
            return tf.Variable(initial)
    
    #===============================================================#
        def bias_variable(self, shape):
            """
            初始化bias(const)
            :param shape:
            :return:
            """
            initial = tf.constant(0.01, shape=shape)
            return tf.Variable(initial)
    
  2. ϵ − g r e e d y \epsilon-greedy ϵgreedy 策略 定义,这里对 ϵ \epsilon ϵ进行一个随时间步的迁移而减小的策略,使其动作选择的不确定性逐渐减小。

    def egreedy_action(self, state):
        """
        epsilon-greedy策略
        :param state:
        :return:
        """
        Q_value = self.Q_value.eval(feed_dict={
            self.state_input: [state]
        })[0]
        if random.random() <= self.epsilon:
            self.epsilon -= (INITIAL_EPSILON - FINAL_EPSILON) / 10000
            return random.randint(0, self.action_dim - 1)
        else:
            self.epsilon -= (INITIAL_EPSILON - FINAL_EPSILON) / 10000
            return np.argmax(Q_value)
  1. Replay buffer的定义

        def perceive(self, state, action, reward, next_state, done):
            """
            Replay buffer
            :param state:
            :param action:
            :param reward:
            :param next_state:
            :param done:
            :return:
            """
            # 对action 进行one-hot存储,方便网络进行处理
            # [0,0,0,0,1,0,0,0,0] action=5
            one_hot_action = np.zeros(self.action_dim)
            one_hot_action[action] = 1
    
            # 存入replay_buffer
            # self.replay_buffer = deque()
            self.replay_buffer.append((state, one_hot_action, reward, next_state, done))
    
            # 溢出出队
            if len(self.replay_buffer) > REPLAY_SIZE:
                self.replay_buffer.popleft()
                
            # 可进行训练条件
            if len(self.replay_buffer) > BATCH_SIZE:
                self.train_Q_network()
    
  2. Q网络训练

    def train_Q_network(self):
        """
        Q网络训练
        :return:
        """
        self.time_step += 1
        # 从 replay buffer D中随机选取 batch size N条数据<s_j,a_j,r_j,s_j+1,done>   D_selected
        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]

        # 计算目标Q值y
        y_batch = []
        Q_value_batch = self.target_Q_value.eval(feed_dict={self.state_input: next_state_batch})
        for i in range(0, BATCH_SIZE):
            done = minibatch[i][4]
            if done:
                y_batch.append(reward_batch[i])
            else:
                y_batch.append(reward_batch[i] + GAMMA * np.max(Q_value_batch[i]))

        self.optimizer.run(feed_dict={
            self.y_input: y_batch,
            self.action_input: action_batch,
            self.state_input: state_batch
        })
  1. Soft update

        def update_target_q_network(self, episode):
           # 更新 target Q netowrk
           if episode % REPLACE_TARGET_FREQ == 0:
    

三、实验结果

环境 cart-pole-v0 (期望回报是200)


四、DQN参考论文流程:

img

五、Double DQN

DQN存在的问题是Q function容易过拟合,根据状态 s t + 1 s_{t+1} st+1 选择动作 a t + 1 a_{t+1} at+1 的过程,以及估计 Q ( s t + 1 , a t + 1 ) ​ Q(s_{t+1},a_{t+1})​ Q(st+1,at+1) 使用的同一个Q net网络参数,这可能导致选择过高的估计值,从而导致过于乐观的值估计。为了避免这种情况的出现,可以对选择和衡量进行解耦,从而就有了使用 Double DQN 来解决这一问题。

Double DQN与DQN的区别仅在于 y y y的求解方式不同,Double DQN根据Q网络参数来选择动作 a t + 1 a_{t+1} at+1,再用Target Q网络参数来衡量 Q ( s t + 1 , a t + 1 ) Q(s_{t+1},a_{t+1}) Q(st+1,at+1)的值。
Y t D Q N = R t + 1 + γ Q ^ ( S t + 1 , a r g m a x a Q ^ ( S t + 1 , a ; θ t − ) ; θ t − ) Y t D D Q N = R t + 1 + γ Q ^ ( S t + 1 , a r g m a x a Q ( S t + 1 , a ; θ t ) ; θ t − ) Y_t^{DQN}=R_{t+1}+\gamma \hat{Q}(S_{t+1},argmax_a\hat{Q}(S_{t+1},a;\theta_t^-);\theta_t^-)\\ Y_t^{DDQN}=R_{t+1}+\gamma \hat{Q}(S_{t+1},argmax_aQ(S_{t+1},a;\theta_t);\theta_t^-) YtDQN=Rt+1+γQ^(St+1,argmaxaQ^(St+1,a;θt);θt)YtDDQN=Rt+1+γQ^(St+1,argmaxaQ(St+1,a;θt);θt)
反映在代码上,就是训练的时候选择Q的时候有点变动:

    def train_Q_network(self):
        """
        Q网络训练
        :return:
        """
        self.time_step += 1
        # 从 replay buffer D中随机选取 batch size N条数据<s_j,a_j,r_j,s_j+1,done>$  D_selected
        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]

        # 计算目标Q值y
        y_batch = []
        QTarget_value_batch = self.target_Q_value.eval(feed_dict={self.state_input: next_state_batch})
        Q_value_batch = self.Q_value.eval(feed_dict={self.state_input: next_state_batch})
        for i in range(0, BATCH_SIZE):
            done = minibatch[i][4]
            if done:
                y_batch.append(reward_batch[i])
            else:
                #################用target Q(Q)#######################
                if DOUBLE_DQN:
                    selected_q_next = QTarget_value_batch[i][np.argmax(Q_value_batch[i])]
                #################用target Q(target Q)################
                else:
                    selected_q_next = np.max(QTarget_value_batch[i])

                y_batch.append(reward_batch[i] + GAMMA * selected_q_next)

        self.optimizer.run(feed_dict={
            self.y_input: y_batch,
            self.action_input: action_batch,
            self.state_input: state_batch
        })

六、DQN,DDQN实验结果对比

可以看到DoubleDQN的表现比 DQN稳定

七、 Dueling DDQN

八、 Dueling DQN, DDQN, DQN对比

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[强化学习笔记专题(二)]Nature DQN 的相关文章

  • 代码解读二 文件名“Ano_Math.c”

    这里面都是一些关于数学函数的骚操作 xff0c 既然不使用math h xff0c 那么至少说明这里面的数学函数调用不应比math h里面的函数慢 下面贴出代码 xff0c 简要做了个注释 xff0c 看看就行 至于怎么做的 xff0c 有
  • 关于单级PID及串级PID

    简单记录下我在学习PID过程中遇到的困难及解决方法 xff0c 希望能对大家有所帮助 1 首先 xff0c 关于PID这块理论知识必须非常清楚 xff0c 能够自行推导公式 xff0c 包括位置式PID公式和增量式PID公式 2 实现位置式
  • 代码解读三 文件名“Ano_Pid.c”

    关于PID这部分匿名代码里面有很多 xff0c 此文件是最基础的即单级PID的实现 xff0c 后面的关于速度和角速度环的串级PID及高度和高度速度环的串级PID都是以此为基础的 xff0c 所以此文件内容务必搞懂 C COPYRIGHT
  • 代码解读四 文件名“Ano_AttCtrl.c”

    这部分是关于匿名串级PID的 xff0c 我觉得有需要的同学可以直接移植 xff0c 不需要自己写了 xff0c 确实有点麻烦 xff0c 基本上代码里面都注释的很清楚了 xff0c 且由于本人水平有限 xff0c 所以也不是都很懂 xff
  • 代码解读六 文件名“Ano_AltCtrl.c”

    写了一大堆 xff0c 也不知道对不对 xff0c 贴上来让大家看看 include 34 Ano AltCtrl h 34 高度控制 include 34 Ano Imu h 34 include 34 Drv icm20602 h 34
  • 代码解读五 文件名“Ano_LocCtrl.c”

    关于这个位置速度环我还不是很理解 xff0c 因为单凭这一个文件确实看不出来什么东西 xff0c 这并不像角度环和角速度环一样有丰富的理论支撑 xff0c 至少我现在还没看到 xff0c 可能是我水平不够额 xff0c 但这并不妨碍我们继续
  • 代码解读七 文件名“Ano_MotorCtrl.c

    本文件比较简单 xff0c 代码比较少 xff0c 主要涉及解锁后四个电机依次1 2 3 4转动 xff0c 然后四轴也不会飞 xff0c 只是在原地轻微转动 xff0c 随后需要逐渐加油门至50 到达临界点 xff0c 稍微往上推一点 x
  • 代码解读八 文件名“Ano_FlightCtrl.c”

    这个文件代码有点乱啊 xff0c 反正没怎么看懂 xff0c 涉及到一键起飞和降落 xff0c 以及关于不同任务对应不同的灯光的切换 而且注释也还可以 xff0c 凑活着看下呗 xff0c 其实这个并不是什么关键文件 xff0c 看不懂就算
  • 代码解读九 文件名“Ano_MagProcess.c”

    本部分主要是关于磁力计进行校准操作的 xff0c 用户手册上有详细步骤 xff0c 有需要可以看看 include 34 Ano MagProcess h 34 include 34 Drv LED h 34 本文件是关于磁力计校准及相关处
  • 代码解读十 文件名“Ano_FlightDataCal.c”

    本部分主要是对IMU测量模块测量的值进行后续处理 xff0c 同时在飞行过程中不断对数据进行更新 xff0c 然后进行姿态解算 xff0c 便于后续丢进PID中进行进一步处理 根据所处位置及函数调用情况不难发现此部分算是对底层的进一步封装
  • 【阅读笔记】联邦学习实战——联邦学习攻防实战

    联邦学习实战 联邦学习攻防实战 前言1 后门攻击1 1 问题定义1 2 后门攻击策略1 3 详细实现 2 差分隐私2 1 集中式差分隐私2 2 联邦差分隐私2 3 详细实现 3 模型压缩3 1 参数稀疏化3 1 1 详细实现3 1 2 实验
  • 关于后续部分

    关于算法这块基本上算是读完了 xff0c 只能从大致上理解下了 xff0c 毕竟代码不是自己写的没有最直接的感受 xff0c 那么我们来回顾下 xff0c 试着从整体上来理解下匿名代码除了最上层之外的部分 最上层也就是包含main c在内的
  • cmake:设置编译选项

    此文为 xff1a 轻松入门cmake系列教程 常用 1 cmake debug和release设置 span class token macro property span class token directive hash span
  • cmake:pkg_check_modules

    此文为 xff1a 轻松入门cmake系列教程 理论 是什么 xff1f pkg check modules是 CMake 自己的 pkg config 模块的一个用来简化的封装 xff1a 你不用再检查 CMake 的版本 xff0c 加
  • Unix/Linux编程:针对目录文件描述符的相关操作

    始于版本2 6 16 xff0c Linux内核提供了一系列新的系统调用 xff0c 在执行与传统系统调用相似任务的同时 xff0c 还提供了一些附加功能 xff0c 对某些应用程序非常有用 新 接 口类似的传统接口备 注faccessat
  • ROS:参数服务器通信

    为什么需要 在机器人开发中 xff0c 会有很多参数和设置可以后期需要调整的 xff0c 如果都放到源码里很难实现动态修改和管理 xff0c ROS2为了解决这一问题 xff0c 提出了参数这一通信机制 是什么 如何理解 参数 xff1f
  • MySQL面试:查询性能的优化方法

    实践中如何优化MySQL 四条从效果上第一条影响最大 xff0c 后面越来越小 SQL语句以及索引的优化数据库表结构的优化系统配置的优化硬件优化 查询性能的优化方法 减少请求的数据量 只返回必要的列 xff1a 最好不要使用 SELECT
  • 基础:怎样理解Linux软中断

    软中断 softirq CPU使用率升高也是最常见的一种性能问题 从 取外卖 看中断 中断是系统用来响应硬件设备请求的一种机制 它会打断进程的正常调度和执行 xff0c 然后调用内核中的中断处理程序来响应设备的请求 为什么要有中断呢 xff
  • HTTP:HTTP报文是什么样子的

    引言 如果说HTTP是因特网的信使 xff0c 那么HTTP报文就是它用来搬东西的包裹了HTTP报文是在HTTP应用程序之间发送的数据块 这些数据块以一些文本形式的元信息 meta information 开头 xff0c 这些信息模式了报
  • ROS:服务通信

    话题通信的数据传输是单向的 xff0c 订阅端被动接收发布端的数据 这时候有人就问了 xff0c 如果发布端想主动接收数据怎么办 ROS中提供了另一种通信方式 xff1a 服务通信 ROS xff1a 通信模型 Service通信是双向的

随机推荐

  • linux操作系统:线程,令复杂的项目并行执行

    为什么要有线程 其实 xff0c 对于任何一个进程来讲 xff0c 即使我们没有主动去创建线程 xff0c 进程也是默认会有一个主线程的 线程是负责执行二进制指令的 xff0c 它会根据项目执行计划书 xff08 二进制文件 xff09 一
  • 存储创建及openstack对接——LVM

    说明 本方案是在每一个计算节点 上安装cinder volumes组件来完成对本地存储的管理 若无特殊说明 xff0c 以下步骤仅在计算节点执行 1 前期准备 检查计算节点是否安装 lvm xff0c iscsi 磁盘分区和格式化 裸盘不能
  • clion:输出中文乱码终极解决方案

    临时解决方案 如果在windows时发现clion乱码 xff0c 可以在cmakelist txt中 xff1a c 43 43 在cmakelist txt添加set CMAKE CXX FLAGS 34 CMAKE CXX FLAGS
  • ROS:节点

    节点 ROS xff1a 节点是什么 机器人是各种功能的综合体 xff0c 每一项功能就像机器人的一个工作细胞 xff0c 众多细胞通过一些机制连接到一起 xff0c 成为了一个机器人整体 在ROS中 xff0c 我们给这些 细胞 取了一个
  • VSCode:配置C/C++开发环境

    准备 区分编辑器 编译器 IDE xff1a 作者 xff1a C语言教学 编辑器就是处理文本 xff08 源码 xff09 的程序 xff0c 写代码写的就是文本 xff0c 编辑器可能提供智能提示 代码高亮等辅助功能 xff0c 但不负
  • NXP MIMXRT1052CVL5B + 正点原子 + MCUXpresso IDE 开发环境搭建

    NXP MIMXRT1052CVL5B 43 正点原子 43 MCUXpresso IDE 开发环境搭建 说明资料准备一切就绪 xff0c 搞他安装 IDE 及生成基本工程安装 J Link 及配置开始调试下载点击 运行 按钮 xff0c
  • c语言学习笔记(1) C语言库函数

    1 xff1a ASLL可现实字符 2 xff1a c文件 span class token macro property span class token directive hash span span class token dire
  • 查看ROS的版本

    查看ROS的版本 启动ROS核心 xff1a roscore获取ROS参数 xff1a rosparam get rosdistro
  • ROS 版本选择和安装

    文章目录 声明 xff1a ROS 的版本选择ROS 的安装ROS 的安装方式软件源安装步骤 声明 xff1a 本文中的内容参考了市面上绝大多数畅销的ROS书籍 xff0c 本文只作个人学习记录和学习分享使用 xff0c 不作任何商业用途
  • 数据结构(考研&面试)

    数据结构和算法 xff08 持续更新 xff09 参考清华大学严蔚敏数据结构与算法 适用于考研 amp 求职 数据结构与算法JAVA落地版 Java 数据结构与算法 xff08 代码实现 下载链接 xff09 本教程全部采用C语言实现 1
  • Sphinx入门

    文章目录 Sphinx画流程图和时序图 最近在使用sphinx的时候遇到了一点问题 xff0c 首先是不支持中文检索 xff0c 为此进行了一些配置 xff0c 参考链接 首先安装jieba库 xff0c python3的安装命令是 xff
  • Linux系统信息查看命令大全

    系统 QUOTE uname a 查看内核 操作系统 CPU信息 head n 1 etc issue 查看操作系统版本 cat proc cpuinfo 查看CPU信息 hostname 查看计算机名 lspci tv 列出所有PCI设备
  • linux系统触摸板用不了(解决)

    安装好linux系统可能出现用不了触摸板的情况 xff0c 只可以单击 xff0c 不可以滑动 解决方式一 sudo modprobe psmouse sudo modprobe r psmouse 解决方式二 sudo modprobe
  • 百度移动软件开发面试题(20131018)

    1 new与malloc的区别 xff1f 分析 xff1a 一 new和malloc都是用于申请动态内存 new使用delete释放空间 xff0c malloc使用free释放 new和delete是C 43 43 中的运算符 xff0
  • Ubuntu 中apt update和upgrade 的区别

    转自https blog csdn net csdn duomaomao article details 77802673 简要说明 xff1a apt update xff1a 只检查 xff0c 不更新 xff08 已安装的软件包是否有
  • ubuntu下域名解析出问题的解决办法

    内网服务器配置了固定ip xff0c 未配置dns xff0c 临时需要接入外网时 xff0c 域名解析失败 xff0c 需要临时添加域名解析 操作如下 xff1a sudo vim etc resolv conf 然后底下插入你的好用的d
  • Git clone wiringPi出现Connection reset by peer的解决办法

    Git clone wiringPi出现Connection reset by peer的解决办法 小伙伴们按照正常的方法来安装强大的GPIO库wiringPi一般为如下几步 xff1a git span class hljs keywor
  • Linux内存占用过高?非也

    前言 今天在我的RPi2上测试GPIO程序 xff0c 忽然发现机器超卡 xff0c 重启之后依然如此 于是我top了一下发现了一个问题就是内存爆满 xff01 xff01 可我还啥都没干呢这是咋了 xff1f 于是我呵呵地开始查资料 xf
  • MPC控制笔记(一)

    转自 我的博客 笔记参考1 xff1a Understanding Model Predictive Control Youtube 带自动生成字幕 笔记参考2 xff1a Understanding Model Predictive Co
  • [强化学习笔记专题(二)]Nature DQN

    转自 我的博客 DQN Nature 一 算法流程 xff1a 定义可配置参数 episode 数量 M最大仿真时间 T xff0c g r