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

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通过优先采样重要经验加速了学习过程。这些改进算法在不同的应用场景下,可以选择合适的算法来提升强化学习的效果。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机组成原理学习笔记(一)

计算机组成原理 [类型:: [[计算机基础课程]] ] [来源:: [[B站]] ] [主讲人:: [[咸鱼学长]] ] [评价:: ] [知识点:: [[系统软件]] & [[应用软件]] ] [简单解释:: 管理计算机系统的软件&#xff1b; 按照任务需要编写的程序 ] [问题:: ] [知识点:: [[机器字长]] ] [简单…

盘点2024年6月Sui生态发展,了解Sui近期成长历程

随着区块链技术的迅猛发展&#xff0c;Sui生态在2024年6月取得了令人欣喜的进步。作为创新的L1协议&#xff0c;Sui不仅在技术革新方面表现突出&#xff0c;还在DeFi、游戏应用和开发者工具等领域展现出强大的潜力。本篇文章将全面盘点Sui在过去一个月内的生态发展&#xff0c;…

【融合ChatGPT等AI模型】Python-GEE遥感云大数据分析、管理与可视化及多领域案例实践应用

随着航空、航天、近地空间遥感平台的持续发展&#xff0c;遥感技术近年来取得显著进步。遥感数据的空间、时间、光谱分辨率及数据量均大幅提升&#xff0c;呈现出大数据特征。这为相关研究带来了新机遇&#xff0c;但同时也带来巨大挑战。传统的工作站和服务器已无法满足大区域…

JavaSE第10篇:常用类

文章目录 一、Object1、Object使用2、toString3、equals和4、hashCode5、clone6、finalize7、getClass8、wait、notify和notifyAll 二、使用步骤 一、Object 1、Object使用 Object类是所有Java的根父类 如果在类的声明中未使用extends关键字指明其父类&#xff0c;则默认父类…

如何监控和优化 PostgreSQL 中的连接池使用?

文章目录 一、连接池的基本概念二、监控 PostgreSQL 连接池使用的重要性&#xff08;一&#xff09;性能优化&#xff08;二&#xff09;资源管理&#xff08;三&#xff09;故障排查 三、PostgreSQL 连接池监控指标&#xff08;一&#xff09;活跃连接数&#xff08;二&#x…

数据结构练习

1. 快速排序的非递归是通过栈来实现的&#xff0c;则前序与层次可以通过控制入栈的顺序来实现&#xff0c;因为递归是会一直开辟栈区空间&#xff0c;所以非递归的实现只需要一个栈的大小&#xff0c;而这个大小是小于递归所要的&#xff0c; 非递归与递归的时间复杂度是一样的…

springboot解压文件流zip压缩包

springboot解压文件流zip压缩包 原始文件存储的地方&#xff1a; 需要在当前目录下解压该文件&#xff0c;如下图&#xff1a; 代码示例&#xff1a; private Result<String> getLocationGuideLayerName(YbYstbtqTaskResolveParam params, String fishnetLayerName)…

我们严重低估了MiniMax;扎克伯格站在了奥特曼的对面;欧洲最强大模型的天才创始人;Notion AI在LLM来临时快速转身奔跑 | ShowMeAI

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; 1. MiniMax 创始人闫俊杰&#xff1a;我选的技术路线是上限最高的&#xff0c;几乎没有退路&#xff0c;选的算力方式也激进 MiniMax 官网 → https:…

30多款简洁个人博客网站网页模板演示学习

30多款个人博客个人网站divcss,html在线预览,静态页面模板免费下载.这些简洁和优雅的博客网页模板,为那些想成为创建博客的个人或媒体提供灵感设计。网页模板可以记录旅游、生活方式、食品或摄影博客等网站。 http://www.bokequ.com/blog/1/ http://www.bokequ.com/blog/2/ htt…

近千含分步骤做法图片菜谱ACCESS\EXCEL数据库

菜谱类的数据已经有一些了&#xff0c;比如《近5万份有图菜谱大全》、《3万多条含图片的菜谱资料数据库》、《无图片的2万多条菜谱》、《5000个菜谱食谱大全》、《4千多带图片的美食菜谱数据内容采集》&#xff0c;但是我还是偏向更喜欢有步骤图片的菜谱&#xff0c;比如《2千8…

2025 百度提前批校招内推

百度2025校园招聘内推开始啦&#xff0c;被推荐人可以免笔试直接面试&#xff0c;提前批结果不影响校招&#xff0c;机会1&#xff0c;还可直推心仪部门&#xff0c;可扫描下面二维码或点击链接进行投递&#xff0c;快来投递你心仪的职位吧&#xff08; 网申链接地址 &#xff…

机器学习的遗忘——基于文章“Forgetting“ in Machine Learning and Beyond: A Survey

文章概要 这篇调查文章仅关注选择性遗忘&#xff0c;承认遗忘某些信息可以通过允许模型优先考虑和保留更重要或相关的信息&#xff0c;以及保护用户隐私&#xff0c;从而带来好处。选择性遗忘&#xff08;Selective forgetting&#xff09;涉及有选择地忽略无关或噪声数据。这…

C语言 | Leetcode C语言题解之第220题存在重复元素III

题目&#xff1a; 题解&#xff1a; struct HashTable {int key;int val;UT_hash_handle hh; };int getID(int x, long long w) {return x < 0 ? (x 1ll) / w - 1 : x / w; }struct HashTable* query(struct HashTable* hashTable, int x) {struct HashTable* tmp;HASH_F…

亚马逊如何用自养号测评打造权重提升排名带来更多的自然流量

亚马逊通过自养号测评来提升流量是一种被广泛采用的运营手段&#xff0c;它可以帮助卖家快速提高商品的曝光度和吸引潜在买家。以下是自养号测评的详细分析&#xff1a; 一、自养号测评的定义与原理 自养号测评是指卖家通过注册并管理海外买家账号&#xff0c;对自家商品进行…

PyQT: 开发一款ROI绘制小程序

在一些基于图像或者视频流的应用中&#xff0c;比如电子围栏/客流统计等&#xff0c;我们需要手动绘制一些感兴趣&#xff08;Region of Interest&#xff0c;简称ROI&#xff09;区域。 在这里&#xff0c;我们基于Python和PyQt5框架开发了一款桌面应用程序&#xff0c;允许用…

java中Request和Response的详细介绍

1.Request和Response的概述 # 重点 1. service方法的两个参数request和response是由tomcat创建的void service(ServletRequest var1, ServletResponse var2) 2. request 表示请求数据, tomcat将浏览器发送过来的请求数据解析并封装到request对象中servlet开发者可以通过reques…

AI免费英语学习在线工具:Pi;gpt;其他大模型AI 英语学习智能体工具

1、pi(强烈推荐&#xff1a;可以安卓下载使用) https://pi.ai/talk &#xff08;网络国内使用方便&#xff09; 支持实时聊天与语音对话 2、chatgpt&#xff08;强烈推荐&#xff1a;可以安卓下载使用) https://chat.openai.com/ &#xff08;网络国内使用不方便&#xf…

element-ui el-select选择器组件下拉框增加自定义按钮

element-ui el-select选择器组件下拉框增加自定义按钮 先看效果 原理&#xff1a;在el-select下添加禁用的el-option&#xff0c;将其value绑定为undefined&#xff0c;然后覆盖el-option禁用状态下的默认样式即可 示例代码如下&#xff1a; <template><div class…

27_电子电路设计基础

电路设计 电路板的设计 电路板的设计主要分三个步骤&#xff1a;设计电路原理图、生成网络表、设计印制电路板。 (1)设计电路原理图&#xff1a;将元器件按逻辑关系用导线连接起来。设计原理图的元件来源是“原理图库”,除了元件库外还可以由用户自己增加建立新的元件&#…

@Builder注解详解:巧妙避开常见的陷阱

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 Builder注解详解&#xff1a;巧妙避开常见的陷阱 前言1. Builder的基本使用使用示例示例类创建对…