强化学习中的Double DQN、Dueling DQN和PER DQN算法详解及实战

news2024/11/25 12:50:45

1. 深度Q网络(DQN)回顾

DQN通过神经网络近似状态-动作值函数(Q函数),在训练过程中使用经验回放(Experience Replay)和固定目标网络(Fixed Target Network)来稳定训练过程。DQN的更新公式为:

Q(s, a) \leftarrow Q(s, a) + \alpha [r + \gamma \max_{a'} Q(s', a') - Q(s, a)]

2. Double DQN算法

原理

DQN存在一个问题,即在更新Q值时,使用同一个Q网络选择和评估动作,容易导致过高估计(overestimation)问题。Double DQN(Double Deep Q-Network, DDQN)通过引入两个Q网络,分别用于选择动作和评估动作,来缓解这一问题。

公式推导

Double DQN的更新公式为:

Q(s, a) \leftarrow Q(s, a) + \alpha [r + \gamma Q(s', \arg\max_{a'} Q(s', a'; \theta); \theta^- ) - Q(s, a)]

其中:

  • \theta 是当前Q网络的参数。
  • \theta^{-} 是目标Q网络的参数。
代码实现

我们以经典的OpenAI Gym中的CartPole环境为例,展示Double DQN算法的实现。

import gym
import numpy as np
import tensorflow as tf
from tensorflow.keras import models, layers, optimizers

class DoubleDQNAgent:
    def __init__(self, state_size, action_size):
        self.state_size = state_size
        self.action_size = action_size
        self.memory = []
        self.gamma = 0.95
        self.epsilon = 1.0
        self.epsilon_decay = 0.995
        self.epsilon_min = 0.01
        self.learning_rate = 0.001
        self.model = self._build_model()
        self.target_model = self._build_model()
        self.update_target_model()
    
    def _build_model(self):
        model = models.Sequential()
        model.add(layers.Dense(24, input_dim=self.state_size, activation='relu'))
        model.add(layers.Dense(24, activation='relu'))
        model.add(layers.Dense(self.action_size, activation='linear'))
        model.compile(loss='mse', optimizer=optimizers.Adam(learning_rate=self.learning_rate))
        return model
    
    def update_target_model(self):
        self.target_model.set_weights(self.model.get_weights())
    
    def remember(self, state, action, reward, next_state, done):
        self.memory.append((state, action, reward, next_state, done))
    
    def act(self, state):
        if np.random.rand() <= self.epsilon:
            return np.random.choice(self.action_size)
        q_values = self.model.predict(state)
        return np.argmax(q_values[0])
    
    def replay(self, batch_size):
        minibatch = np.random.choice(self.memory, batch_size)
        for state, action, reward, next_state, done in minibatch:
            target = self.model.predict(state)
            if done:
                target[0][action] = reward
            else:
                t = self.model.predict(next_state)
                t_ = self.target_model.predict(next_state)
                target[0][action] = reward + self.gamma * t_[0][np.argmax(t[0])]
            self.model.fit(state, target, epochs=1, verbose=0)
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay

env = gym.make('CartPole-v1')
state_size = env.observation_space.shape[0]
action_size = env.action_space.n
agent = DoubleDQNAgent(state_size, action_size)
episodes = 1000

for e in range(episodes):
    state = env.reset()
    state = np.reshape(state, [1, state_size])
    done = False
    time = 0
    while not done:
        action = agent.act(state)
        next_state, reward, done, _ = env.step(action)
        next_state = np.reshape(next_state, [1, state_size])
        reward = reward if not done else -10
        agent.remember(state, action, reward, next_state, done)
        state = next_state
        time += 1
        if done:
            agent.update_target_model()
            print(f"Episode: {e}/{episodes}, Score: {time}, Epsilon: {agent.epsilon:.2}")
        if len(agent.memory) > 32:
            agent.replay(32)

env.close()
print("Double DQN训练完成")

3. Dueling DQN算法

原理

Dueling DQN通过将Q值函数拆分为状态价值(Value)和优势函数(Advantage),分别估计某一状态下所有动作的价值和某一动作相对于其他动作的优势。这样可以更好地评估状态的价值,从而提高算法性能。

公式推导

Dueling DQN的Q值函数定义为:

Q(s, a; \theta, \alpha, \beta) = V(s; \theta, \beta) + (A(s, a; \theta, \alpha) - \frac{1}{|\mathcal{A}|} \sum_{a'} A(s, a'; \theta, \alpha)) 

其中:

  • V(s; \theta, \beta)是状态价值函数。
  • A(s, a; \theta, \alpha)是优势函数。
代码实现

以CartPole环境为例,展示Dueling DQN算法的实现。

import gym
import numpy as np
import tensorflow as tf
from tensorflow.keras import models, layers, optimizers

class DuelingDQNAgent:
    def __init__(self, state_size, action_size):
        self.state_size = state_size
        self.action_size = action_size
        self.memory = []
        self.gamma = 0.95
        self.epsilon = 1.0
        self.epsilon_decay = 0.995
        self.epsilon_min = 0.01
        self.learning_rate = 0.001
        self.model = self._build_model()
        self.target_model = self._build_model()
        self.update_target_model()
    
    def _build_model(self):
        input = layers.Input(shape=(self.state_size,))
        dense1 = layers.Dense(24, activation='relu')(input)
        dense2 = layers.Dense(24, activation='relu')(dense1)
        
        value_fc = layers.Dense(24, activation='relu')(dense2)
        value = layers.Dense(1, activation='linear')(value_fc)
        
        advantage_fc = layers.Dense(24, activation='relu')(dense2)
        advantage = layers.Dense(self.action_size, activation='linear')(advantage_fc)
        
        q_values = layers.Lambda(lambda x: x[0] + (x[1] - tf.reduce_mean(x[1], axis=1, keepdims=True)))([value, advantage])
        
        model = models.Model(inputs=input, outputs=q_values)
        model.compile(loss='mse', optimizer=optimizers.Adam(learning_rate=self.learning_rate))
        return model
    
    def update_target_model(self):
        self.target_model.set_weights(self.model.get_weights())
    
    def remember(self, state, action, reward, next_state, done):
        self.memory.append((state, action, reward, next_state, done))
    
    def act(self, state):
        if np.random.rand() <= self.epsilon:
            return np.random.choice(self.action_size)
        q_values = self.model.predict(state)
        return np.argmax(q_values[0])
    
    def replay(self, batch_size):
        minibatch = np.random.choice(self.memory, batch_size)
        for state, action, reward, next_state, done in minibatch:
            target = self.model.predict(state)
            if done:
                target[0][action] = reward
            else:
                t = self.target_model.predict(next_state)
                target[0][action] = reward + self.gamma * np.amax(t[0])
            self.model.fit(state, target, epochs=1, verbose=0)
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay

env = gym.make('CartPole-v1')
state_size = env.observation_space.shape[0]
action_size = env.action_space.n
agent = DuelingDQNAgent(state_size, action_size)

episodes = 1000

for e in range(episodes):
    state = env.reset()
    state = np.reshape(state, [1, state_size])
    done = False
    time = 0
    while not done:
        action = agent.act(state)
        next_state, reward, done, _ = env.step(action)
        next_state = np.reshape(next_state, [1, state_size])
        reward = reward if not done else -10
        agent.remember(state, action, reward, next_state, done)
        state = next_state
        time += 1
        if done:
            agent.update_target_model()
            print(f"Episode: {e}/{episodes}, Score: {time}, Epsilon: {agent.epsilon:.2}")
        if len(agent.memory) > 32:
            agent.replay(32)

env.close()
print("Dueling DQN训练完成")

4. 优先经验回放DQN(PER DQN)

原理

优先经验回放(Prioritized Experience Replay, PER)通过赋予不同经验样本不同的优先级来增强经验回放机制。优先级高的样本更有可能被再次抽取,从而加速学习过程。

公式推导

优先经验回放基于TD误差计算优先级,定义为:

p_i = | \delta_i | + \epsilon

其中:

  • \delta_i 是TD误差。
  • \epsilon 是一个小的正数,防止优先级为零。

然后根据优先级分布概率来采样,使用重要性采样权重来修正梯度更新,定义为:

w_i = \left( \frac{1}{N} \cdot \frac{1}{P(i)} \right)^\beta

代码实现

以CartPole环境为例,展示PER DQN算法的实现。

import gym
import numpy as np
import tensorflow as tf
from tensorflow.keras import models, layers, optimizers
import random
import collections

class PERDQNAgent:
    def __init__(self, state_size, action_size):
        self.state_size = state_size
        self.action_size = action_size
        self.memory = collections.deque(maxlen=2000)
        self.gamma = 0.95
        self.epsilon = 1.0
        self.epsilon_decay = 0.995
        self.epsilon_min = 0.01
        self.learning_rate = 0.001
        self.model = self._build_model()
        self.target_model = self._build_model()
        self.update_target_model()
        self.priority = []
        self.alpha = 0.6
        self.beta = 0.4
        self.beta_increment_per_sampling = 0.001

    def _build_model(self):
        model = models.Sequential()
        model.add(layers.Dense(24, input_dim=self.state_size, activation='relu'))
        model.add(layers.Dense(24, activation='relu'))
        model.add(layers.Dense(self.action_size, activation='linear'))
        model.compile(loss='mse', optimizer=optimizers.Adam(learning_rate=self.learning_rate))
        return model
    
    def update_target_model(self):
        self.target_model.set_weights(self.model.get_weights())
    
    def remember(self, state, action, reward, next_state, done):
        self.memory.append((state, action, reward, next_state, done))
        self.priority.append(max(self.priority, default=1))

    def act(self, state):
        if np.random.rand() <= self.epsilon:
            return np.random.choice(self.action_size)
        q_values = self.model.predict(state)
        return np.argmax(q_values[0])

    def replay(self, batch_size):
        if len(self.memory) < batch_size:
            return
        priorities = np.array(self.priority)
        sampling_probabilities = priorities ** self.alpha
        sampling_probabilities /= sampling_probabilities.sum()
        indices = np.random.choice(len(self.memory), batch_size, p=sampling_probabilities)
        minibatch = [self.memory[i] for i in indices]
        importance_sampling_weights = (len(self.memory) * sampling_probabilities[indices]) ** (-self.beta)
        importance_sampling_weights /= importance_sampling_weights.max()

        for i, (state, action, reward, next_state, done) in enumerate(minibatch):
            target = self.model.predict(state)
            if done:
                target[0][action] = reward
            else:
                t = self.target_model.predict(next_state)
                target[0][action] = reward + self.gamma * np.amax(t[0])
            self.model.fit(state, target, epochs=1, verbose=0, sample_weight=importance_sampling_weights[i])
            self.priority[indices[i]] = abs(target[0][action] - self.model.predict(state)[0][action]) + 1e-6

        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay
        self.beta = min(1.0, self.beta + self.beta_increment_per_sampling)

env = gym.make('CartPole-v1')
state_size = env.observation_space.shape[0]
action_size = env.action_space.n
agent = PERDQNAgent(state_size, action_size)
episodes = 1000

for e in range(episodes):
    state = env.reset()
    state = np.reshape(state, [1, state_size])
    done = False
    time = 0
    while not done:
        action = agent.act(state)
        next_state, reward, done, _ = env.step(action)
        next_state = np.reshape(next_state, [1, state_size])
        reward = reward if not done else -10
        agent.remember(state, action, reward, next_state, done)
        state = next_state
        time += 1
        if done:
            agent.update_target_model()
            print(f"Episode: {e}/{episodes}, Score: {time}, Epsilon: {agent.epsilon:.2}")
        if len(agent.memory) > 32:
            agent.replay(32)

env.close()
print("PER DQN训练完成")

5. 总结

Double DQN、Dueling DQN和优先经验回放DQN(PER DQN)都是对原始DQN的改进,各有其优点和适用场景。Double DQN通过减少过高估计提高了算法的稳定性;Dueling DQN通过分离状态价值和优势函数更好地评估状态;PER DQN通过优先采样重要经验加速了学习过程。这些改进算法在不同的应用场景下,可以选择合适的算法来提升强化学习的效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1904090.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【踩坑】修复pyinstaller报错 No module named pkg_resources.extern

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 报错如下&#xff1a; 修复方法&#xff1a; pip install --upgrade setuptools pippyinstaller -F -w main.py --hidden-importpkg_resources.py2_wa…

VMware安装centos9详细教程(保姆级)

前言 centos9最新的centos版本&#xff0c;在近期的使用中发现它的操作界面与以往的centos7/8更加舒适&#xff0c;界面优化更加精细 项目终止日期&#xff08;EOL&#xff09; 从公告可知&#xff0c;CentOS 项目重心从 CentOS Linux 转移到了 CentOS Stream。下面是各个项…

Spring的核心概念理解案列

IDEA开发的简单“登陆成功”小项目 IDEA项目结构&#xff1a; 每一部分代码和相应的解读&#xff1a; com.itTony文件下有dao&#xff08;实体&#xff09;层&#xff0c;service&#xff08;服务&#xff09;层&#xff0c;编写的2个类&#xff08;HelloSpring和TestSpring&…

ORA-12170: TNS:连接超时

今天在oracle数据库搭建连接远程数据库的dbink时&#xff0c;发现搭建失败报错&#xff1a;ORA-12170: TNS:连接超时 但是是能够ping的通远程数据库地址的。 telnet 172.18.6.104 1522要求查看下创建dblink语句&#xff0c;也确认创建语句无误。 (DESCRIPTION (ADDRESS_LIST…

使用labelme中的AI多边形(AI-polygon)标注 win版exe Create AI-Polygon闪退

这里写目录标题 虚拟环境创建labelme虚拟环境下载AI标注模型win Labelme.exe Create AI-Polygon闪退问题也用如下方法解决 win Labelme.exe Create AI-Polygon闪退问题也用如下方法解决愉快地使用labelme的AI标注工具 虚拟环境 创建labelme虚拟环境 创建基础环境并激活 cond…

顺序表的介绍

前言 大家好&#xff0c;作者菌又来了&#xff0c;今天我们开始顺序表的学习&#xff0c;今天的内容十分的简单&#xff0c;就是带领大家简单了解顺序表&#xff0c;那好话不多说&#xff0c;直接开始我们今天的正题&#xff01;&#xff01; 1.顺序表的概念和结构 线性表…

驾校管理系统的全面革新与升级

智慧驾校系统是一款专为现代驾校量身定制的综合性管理平台,它深度融合了云计算、大数据、物联网及人工智能等前沿技术,旨在为驾校打造一个高效、智能、便捷的运营生态系统。该系统通过数字化、信息化的手段,彻底革新了传统驾校的管理模式,不仅极大地提升了驾校的运营效率,…

智慧校园-基础平台功能总体概述

智慧校园基础平台是现代教育信息化的核心&#xff0c;它集成了系统管理、基础数据、系统监控、系统工具、流程管理等关键功能&#xff0c;构建了一个全面、智能、安全的校园生态系统。系统管理部分&#xff0c;通过权限管理和用户管理&#xff0c;实现了对用户访问权限的精细化…

【Qt】Qt开发环境搭建

目录 一. Qt SDK的下载&安装 二. Qt相关工具介绍 Qt的常用开发工具有&#xff1a; Qt CreatorVisual StudioEclipse 一. Qt SDK的下载&安装 Qt 下载官网&#xff1a; http://download.qt.io/archive/qt/ 国内清华源: https://mirrors.tuna.tsinghua.edu.cn/qt/arc…

freemarker生成pdf,同时pdf插入页脚,以及数据量大时批量处理

最近公司有个需求&#xff0c;就是想根据一个模板生成一个pdf文档&#xff0c;当即我就想到了freemarker这个远古老东西&#xff0c;毕竟freemarker在模板渲染方面还是非常有优势的。 准备依赖&#xff1a; <dependency><groupId>org.springframework.boot</gr…

【讲解下iOS语言基础】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【论文阅读】-- Visual Traffic Jam Analysis Based on Trajectory Data

基于轨迹数据的可视化交通拥堵分析 摘要1 引言2 相关工作2.1 交通事件检测2.2 交通可视化2.3 传播图可视化 3 概述3.1 设计要求3.2 输入数据说明3.3 交通拥堵数据模型3.4 工作流程 4 预处理4.1 路网处理4.2 GPS数据清理4.3 地图匹配4.4 道路速度计算4.5 交通拥堵检测4.6 传播图…

Halcon 产品周围缺口检测

*读取一张图像read_image (Image, 原图.jpg)*获取图像大小get_image_size(Image, Width, Height)*关闭已经打开的窗口dev_close_window ()*打开新窗口dev_open_window(0, 0, Width, Height, black, WindowHandle) //打开指定大小的窗口*对图像进行阈值操作threshold (Image, R…

C语言 指针和数组—指针数组及其在字符串处理中的应用

目录 问题的提出 问题的解决 回头看——指针、数组及其他类型的混合 指针数组与指向数组的指针 字符串的排序 问题的提出 问题的解决 回头看——指针、数组及其他类型的混合  基本数据类型  int 、 long 、 char 、 short 、 float 、 double……  数组是一种从…

001,函数指针是一种特殊的指针,它指向的是一个函数地址,可以存储函数并作为参数传递,也可以用于动态绑定和回调函数

函数指针是一种特殊的指针 001&#xff0c;函数指针是一种特殊的指针&#xff0c;它指向的是一个函数地址&#xff0c;可以存储函数并作为参数传递&#xff0c;也可以用于动态绑定和回调函数 文章目录 函数指针是一种特殊的指针前言总结 前言 这是ai回答的标准答案 下面我们…

SSM中小学生信息管理系统 -计算机毕业设计源码02677

摘要 随着社会的发展和教育的进步&#xff0c;中小学生信息管理系统成为学校管理的重要工具。本论文旨在基于SSM框架&#xff0c;采用Java编程语言和MySQL数据库&#xff0c;设计和开发一套高效、可靠的中小学生信息管理系统。中小学生信息管理系统以学生为中心&#xff0c;通过…

手把手搭建微信机器人,帮你雇一个24小时在线的个人 AI 助理(上)

上一篇&#xff0c;带领大家薅了一台腾讯云服务器&#xff1a;玩转云服务&#xff1a;手把手带你薅一台腾讯云服务器&#xff0c;公网 IP。 基于这台服务器&#xff0c;今天我们一起动手捏一个基于 LLM 的微信机器人。 0. 前置准备 除了自己常用的微信账号以外&#xff0c;还…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] LYA的生日聚会(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

【微服务】springboot对接Prometheus指标监控使用详解

目录 一、前言 二、微服务监控概述 2.1 微服务常用监控指标 2.2 微服务常用指标监控工具 2.3 微服务使用Prometheus监控优势 三、环境准备 3.1 部署Prometheus服务 3.2 部署Grafana 服务 3.3 提前搭建springboot工程 3.3.1 引入基础依赖 3.3.2 配置Actuator 端点 3.…

STM32实现看门狗(HAL库)

文章目录 一. 看门狗1. 独立看门狗&#xff08;IWDG&#xff09;1.1 原理1.2 相关配置1.3 相关函数 2. 窗口看门狗&#xff08;WWDG&#xff09;2.1 原理2.2 相关配置2.3 相关函数 一. 看门狗 单片机在日常工作中常常会因为用户配置代码出现BUG&#xff0c;而导致芯片无法正常工…