双深度Q网络(Double DQN)基础解析与python实例:训练稳定倒立摆

目录

1. 前言

2. Double DQN的核心思想

3. Double DQN 实例:倒立摆

4. Double DQN的关键改进点

5. 双重网络更新策略

6. 总结


1. 前言

在强化学习领域,深度Q网络(DQN)开启了利用深度学习解决复杂决策问题的新篇章。然而,标准DQN存在一个显著问题:Q值的过估计。为解决这一问题,Double DQN应运而生,它通过引入两个网络来减少Q值的过估计,从而提高策略学习的稳定性和性能。本文将深入浅出地介绍Double DQN的核心思想,并通过一个完整python实现案例,帮助大家全面理解强化这一学习算法。

2. Double DQN的核心思想

标准DQN使用同一个网络同时选择动作和评估动作价值,这容易导致Q值的过估计。Double DQN通过将动作选择和价值评估分离到两个不同的网络来解决这个问题:

  1. 一个网络(在线网络)用于选择当前状态下的最佳动作

  2. 另一个网络(目标网络)用于评估这个动作的价值

这种分离减少了自举过程中动作选择和价值评估的关联性,从而有效降低了Q值的过估计。

结构如下:

3. Double DQN 实例:倒立摆

接下来,我们将实现一个完整的Double DQN,解决CartPole平衡问题。这个例子包含了所有关键组件:

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import gym
import random
from collections import deque


# 1. 定义DQN网络结构
class DQN(nn.Module):
    def __init__(self, state_dim, action_dim):
        super(DQN, self).__init__()
        self.fc1 = nn.Linear(state_dim, 128)
        self.fc2 = nn.Linear(128, 128)
        self.fc3 = nn.Linear(128, action_dim)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x


# 2. 经验回放缓冲区
class ReplayBuffer:
    def __init__(self, capacity):
        self.buffer = deque(maxlen=capacity)

    def add(self, state, action, reward, next_state, done):
        self.buffer.append((state, action, reward, next_state, done))

    def sample(self, batch_size):
        samples = random.sample(self.buffer, batch_size)
        states, actions, rewards, next_states, dones = zip(*samples)
        return states, actions, rewards, next_states, dones

    def __len__(self):
        return len(self.buffer)


# 3. Double DQN代理
class DoubleDQNAgent:
    def __init__(self, state_dim, action_dim):
        self.policy_net = DQN(state_dim, action_dim)
        self.target_net = DQN(state_dim, action_dim)
        self.target_net.load_state_dict(self.policy_net.state_dict())
        self.target_net.eval()

        self.optimizer = optim.Adam(self.policy_net.parameters(), lr=0.001)
        self.replay_buffer = ReplayBuffer(10000)
        self.batch_size = 64
        self.gamma = 0.99  # 折扣因子
        self.epsilon = 1.0  # 探索率
        self.epsilon_decay = 0.995
        self.min_epsilon = 0.01
        self.action_dim = action_dim

    # 根据ε-greedy策略选择动作
    def select_action(self, state):
        if random.random() < self.epsilon:
            return random.randint(0, self.action_dim - 1)
        else:
            with torch.no_grad():
                return self.policy_net(torch.FloatTensor(state)).argmax().item()

    # 存储经验
    def store_transition(self, state, action, reward, next_state, done):
        self.replay_buffer.add(state, action, reward, next_state, done)

    # 更新网络
    def update(self):
        if len(self.replay_buffer) < self.batch_size:
            return

        # 从经验回放中采样
        states, actions, rewards, next_states, dones = self.replay_buffer.sample(self.batch_size)

        # 转换为PyTorch张量
        states = torch.FloatTensor(states)
        actions = torch.LongTensor(actions)
        rewards = torch.FloatTensor(rewards)
        next_states = torch.FloatTensor(next_states)
        dones = torch.FloatTensor(dones)

        # 计算当前Q值
        current_q = self.policy_net(states).gather(1, actions.unsqueeze(1)).squeeze(1)

        # 计算目标Q值(使用Double DQN方法)
        # 使用策略网络选择动作,目标网络评估价值
        with torch.no_grad():
            # 从策略网络中选择最佳动作
            policy_actions = self.policy_net(next_states).argmax(dim=1)
            # 从目标网络中评估这些动作的值
            next_q = self.target_net(next_states).gather(1, policy_actions.unsqueeze(1)).squeeze(1)
            target_q = rewards + self.gamma * next_q * (1 - dones)

        # 计算损失并优化
        loss = nn.MSELoss()(current_q, target_q)
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()

        # 更新目标网络(软更新)
        for target_param, policy_param in zip(self.target_net.parameters(), self.policy_net.parameters()):
            target_param.data.copy_(0.001 * policy_param.data + 0.999 * target_param.data)

        # 减少探索率
        self.epsilon = max(self.min_epsilon, self.epsilon * self.epsilon_decay)

    # 训练过程


def train_double_dqn():
    # 创建环境
    env = gym.make('CartPole-v1')
    state_dim = env.observation_space.shape[0]
    action_dim = env.action_space.n

    # 创建代理
    agent = DoubleDQNAgent(state_dim, action_dim)

    # 训练参数
    episodes = 500
    max_steps = 500

    # 训练循环
    for episode in range(episodes):
        state, _ = env.reset()
        total_reward = 0

        for step in range(max_steps):
            action = agent.select_action(state)
            next_state, reward, done, _, _ = env.step(action)

            # 修改奖励以加速学习
            reward = reward if not done else -10

            agent.store_transition(state, action, reward, next_state, done)
            agent.update()

            total_reward += reward
            state = next_state

            if done:
                break

        # 每10个episodes更新一次目标网络
        if episode % 10 == 0:
            agent.target_net.load_state_dict(agent.policy_net.state_dict())

        print(f"Episode: {episode + 1}, Total Reward: {total_reward}, Epsilon: {agent.epsilon:.2f}")

    env.close()


# 执行训练
if __name__ == "__main__":
    train_double_dqn()

4. Double DQN的关键改进点

  1. 双网络结构:通过将动作选择(策略网络)和价值评估(目标网络)分离,减少了Q值的过估计。

  2. 经验回放:通过存储和随机采样历史经验,打破了数据的相关性,提高了学习稳定性。

  3. ε-greedy策略:平衡探索与利用,随着训练进行逐渐减少探索概率。

目标网络在Double DQN中扮演着非常重要的角色:

  • 它为策略网络提供稳定的目标Q值

  • 通过延迟更新,减少了目标Q值的波动

  • 与策略网络共同工作,实现了动作选择和价值评估的分离

5. 双重网络更新策略

在Double DQN中,我们使用了软更新(soft update)策略来更新目标网络:

for target_param, policy_param in zip(self.target_net.parameters(), self.policy_net.parameters()):
    target_param.data.copy_(0.001 * policy_param.data + 0.999 * target_param.data)

这种软更新方式比传统的目标网络定期硬更新(hard update)更平滑,有助于训练过程的稳定。

6. 总结

本文通过详细讲解Double DQN的原理,并提供了完整的python实现代码,展示了如何应用这一先进强化学习算法解决实际问题。与标准DQN相比,Double DQN通过引入双网络结构,有效解决了Q值过估计问题,提高了策略学习的稳定性和最终性能。Double DQN是强化学习领域的一个重要进步,为后续更高级的算法(如Dueling DQN、C51、Rainbow DQN等)奠定了基础。通过理解Double DQN的原理和实现,读者可以为进一步探索复杂强化学习算法打下坚实基础。在实际应用中,可以根据具体任务调整网络结构、超参数(如学习率、折扣因子、经验回放缓冲区大小等)以及探索策略,以获得最佳性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙色小博

一起在人工智能领域学习进步!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值