本篇文章是博主强化学习RL领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章强化学习: 强化学习(2)---《【DRL】深度强化学习介绍》
【DRL】深度强化学习介绍
随着深度学习的迅猛发展,深度强化学习(Deep Reinforcement Learning, DRL)将深度学习与强化学习相结合,使得处理高维状态空间成为可能。
1 深度Q网络(DQN)
深度Q网络使用神经网络来近似Q值函数。DQN引入了经验重放(Experience Replay)和目标网络(Target Network)来提高学习稳定性和效率。
DQN的更新步骤
- 从经验池中随机抽取一个小批量的经验。
- 更新Q值函数,使用最小化均方误差(MSE)的方法。
![[ L = \mathbb{E}{s,a,r,s'} \left[ \left( y - Q(s,a; \theta) \right)^2 \right] ]](https://latex.csdn.net/eq?%5B%20L%20%3D%20%5Cmathbb%7BE%7D%7Bs%2Ca%2Cr%2Cs%27%7D%20%5Cleft%5B%20%5Cleft%28%20y%20-%20Q%28s%2Ca%3B%20%5Ctheta%29%20%5Cright%29%5E2%20%5Cright%5D%20%5D)
其中,是目标网络的参数。
2 策略梯度方法
REINFORCE算法
REINFORCE是一种基于蒙特卡罗方法的策略梯度算法,它通过直接对策略进行参数化来优化期望回报。对于给定状态 ( s ) 和动作 ( a ),更新规则如下:
![[ \nabla J(\theta) = \mathbb{E}{\tau \sim \pi\theta} \left[ G_t \nabla \log \pi_\theta(a_t | s_t) \right] ]](https://latex.csdn.net/eq?%5B%20%5Cnabla%20J%28%5Ctheta%29%20%3D%20%5Cmathbb%7BE%7D%7B%5Ctau%20%5Csim%20%5Cpi%5Ctheta%7D%20%5Cleft%5B%20G_t%20%5Cnabla%20%5Clog%20%5Cpi_%5Ctheta%28a_t%20%7C%20s_t%29%20%5Cright%5D%20%5D)
其中:
- 是目标函数,表示期望累计奖励。
- 是从时间步 ( t ) 开始的回报。
- 是在状态 ( s ) 下选择动作 ( a ) 的策略。
这种方法的优势在于它可以处理高维的动作空间,但通常收敛速度较慢。
演员-评论家(Actor-Critic)
演员-评论家方法结合了值函数和策略优化。演员负责生成动作,而评论家则评估这些动作的质量。更新过程同时优化策略和价值估计。
- 演员更新:通过策略梯度法来调整策略。
- 评论家更新:使用时序差分方法更新值函数。
3 深度强化学习的优势与挑战
深度强化学习的优势在于能有效处理复杂、高维的状态空间,如图像和语音等。然而,它也面临着一些挑战,例如:
- 样本效率低:需要大量的交互样本来训练模型。
- 收敛性问题:在某些情况下,可能会出现不稳定或不收敛的问题。
- 超参数调优:需要仔细设置学习率、折扣因子等超参数。
[Python] 深度Q网络(DQN)实现
""" 深度Q网络(DQN)实现
时间:2024.07.27
环境:gym-CartPole-v1
作者:不去幼儿园
"""
import gym
import torch
import torch.nn as nn
import torch.optim as optim
import random
import numpy as np
from collections import deque
# 定义Q网络
class QNetwork(nn.Module):
def __init__(self, state_size, action_size):
super(QNetwork, self).__init__()
# 第一层全连接层,将输入状态映射到64个隐藏单元
self.fc1 = nn.Linear(state_size, 64)
# 第二层全连接层,将64个隐藏单元映射到另一个64个隐藏单元
self.fc2 = nn.Linear(64, 64)
# 输出层,将隐藏单元映射到动作空间的大小
self.fc3 = nn.Linear(64, action_size)
def forward(self, x):
# 前向传播:使用ReLU激活函数
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
return self.fc3(x)
# DQN代理
class DQNAgent:
def __init__(self, state_size, action_size):
self.state_size = state_size # 状态空间的大小
self.action_size = action_size # 动作空间的大小
# 初始化Q网络和目标Q网络
self.qnetwork = QNetwork(state_size, action_size)
self.target_qnetwork = QNetwork(state_size, action_size)
# 优化器使用Adam
self.optimizer = optim.Adam(self.qnetwork.parameters(), lr=0.001)
# 经验回放缓冲区,最大长度为2000
self.memory = deque(maxlen=2000)
self.gamma = 0.99 # 折扣因子
self.epsilon = 1.0 # 探索率
self.epsilon_decay = 0.995 # 探索率衰减
self.epsilon_min = 0.01 # 最小探索率
self.batch_size = 64 # 批次大小
self.update_target_every = 5 # 每5次更新目标网络
self.update_count = 0 # 更新计数器
def remember(self, state, action, reward, next_state, done):
# 将经验存储到记忆中
state = np.array(state, dtype=np.float32)
next_state = np.array(next_state, dtype=np.float32)
self.memory.append((state, action, reward, next_state, done))
def act(self, state):
# 使用epsilon-greedy策略选择动作
if np.random.rand() <= self.epsilon:
return random.choice(range(self.action_size)) # 随机选择动作
state = torch.FloatTensor(state).unsqueeze(0)
with torch.no_grad():
q_values = self.qnetwork(state)
return np.argmax(q_values.numpy()) # 选择Q值最大的动作
def replay(self):
# 经验回放
if len(self.memory) < self.batch_size:
return
batch = random.sample(self.memory, self.batch_size)
states, actions, rewards, next_states, dones = zip(*batch)
states = np.array(states, dtype=np.float32)
actions = np.array(actions)
rewards = np.array(rewards, dtype=np.float32)
next_states = np.array(next_states, dtype=np.float32)
dones = np.array(dones, dtype=np.float32)
states = torch.FloatTensor(states)
actions = torch.LongTensor(actions).unsqueeze(1)
rewards = torch.FloatTensor(rewards)
next_states = torch.FloatTensor(next_states)
dones = torch.FloatTensor(dones)
# 计算当前Q值
q_values = self.qnetwork(states).gather(1, actions).squeeze()
# 计算目标Q值
with torch.no_grad():
next_q_values = self.target_qnetwork(next_states).max(1)[0]
targets = rewards + (self.gamma * next_q_values * (1 - dones))
# 计算损失并进行反向传播
loss = nn.MSELoss()(q_values, targets)
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
# 更新epsilon
if self.epsilon > self.epsilon_min:
self.epsilon *= self.epsilon_decay
self.update_count += 1
# 更新目标网络
if self.update_count % self.update_target_every == 0:
self.target_qnetwork.load_state_dict(self.qnetwork.state_dict())
# 训练DQN的主函数
def train_dqn(env_name, n_episodes=1000):
env = gym.make(env_name, render_mode="human") # 创建环境并设置渲染模式
agent = DQNAgent(env.observation_space.shape[0], env.action_space.n) # 初始化代理
for episode in range(n_episodes):
state, _ = env.reset() # 重置环境并获取初始状态
total_reward = 0
done = False
while not done:
action = agent.act(state) # 根据策略选择动作
step_result = env.step(action) # 执行动作
if len(step_result) == 5: # 如果返回5个值
next_state, reward, done, truncated, _ = step_result
else:
next_state, reward, done, _ = step_result
agent.remember(state, action, reward, next_state, done) # 存储经验
agent.replay() # 经验回放
state = next_state # 更新状态
total_reward += reward
# 每训练100轮显示一次运行界面
if (episode + 1) % 100 == 0:
env.render()
print(f"第 {episode + 1} 轮,总奖励: {total_reward}")
env.close() # 关闭环境
train_dqn('CartPole-v1') # 开始训练
[Python] REINFORCE算法实现
""" REINFORCE算法实现
时间:2024.07.27
环境:gym-CartPole-v1
作者:不去幼儿园
"""
import gym
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
# 定义策略网络
class PolicyNetwork(nn.Module):
def __init__(self, state_size, action_size):
super(PolicyNetwork, self).__init__()
self.fc1 = nn.Linear(state_size, 64) # 第一层全连接层
self.fc2 = nn.Linear(64, action_size) # 输出层
def forward(self, x):
x = torch.relu(self.fc1(x)) # 使用ReLU激活函数
return torch.softmax(self.fc2(x), dim=-1) # 使用Softmax输出概率分布
# REINFORCE代理
class REINFORCEAgent:
def __init__(self, state_size, action_size):
self.policy_network = PolicyNetwork(state_size, action_size) # 初始化策略网络
self.optimizer = optim.Adam(self.policy_network.parameters(), lr=0.001) # 使用Adam优化器
self.gamma = 0.99 # 折扣因子
def select_action(self, state):
state = torch.FloatTensor(state).unsqueeze(0) # 转换状态为张量,并增加一个维度
probs = self.policy_network(state) # 获取动作概率
action = np.random.choice(len(probs[0]), p=probs.detach().numpy()[0]) # 根据概率选择动作
return action, torch.log(probs[0, action]) # 返回动作和对应的对数概率
def update_policy(self, rewards, log_probs):
discounted_rewards = [] # 初始化折扣奖励列表
R = 0 # 初始化累计奖励
for r in reversed(rewards): # 计算折扣奖励
R = r + self.gamma * R
discounted_rewards.insert(0, R) # 插入到列表的开头
discounted_rewards = torch.FloatTensor(discounted_rewards) # 转换为张量
# 标准化奖励
discounted_rewards = (discounted_rewards - discounted_rewards.mean()) / (discounted_rewards.std() + 1e-9)
log_probs = torch.stack(log_probs) # 将对数概率堆叠成一个张量
loss = -torch.sum(log_probs * discounted_rewards) # 计算损失
self.optimizer.zero_grad() # 清零梯度
loss.backward() # 反向传播
self.optimizer.step() # 更新参数
# 训练REINFORCE的主函数
def train_reinforce(env_name, n_episodes=1000):
render = False # 初始化渲染标志为False
for episode in range(n_episodes):
if (episode + 1) % 100 == 0: # 每训练100轮设置渲染标志为True
render = True
else:
render = False
# 创建环境,并根据渲染标志设置渲染模式
env = gym.make(env_name, render_mode="human" if render else None)
agent = REINFORCEAgent(env.observation_space.shape[0], env.action_space.n) # 初始化代理
state, _ = env.reset() # 重置环境并获取初始状态
log_probs = [] # 初始化对数概率列表
rewards = [] # 初始化奖励列表
total_reward = 0 # 初始化总奖励
done = False # 初始化完成标志为False
while not done:
if render:
env.render() # 如果渲染标志为True,渲染环境
action, log_prob = agent.select_action(state) # 选择动作
next_state, reward, done, truncated, _ = env.step(action) # 执行动作
log_probs.append(log_prob) # 存储对数概率
rewards.append(reward) # 存储奖励
state = next_state # 更新状态
total_reward += reward # 更新总奖励
agent.update_policy(rewards, log_probs) # 更新策略
print(f"第 {episode + 1} 轮,总奖励: {total_reward}") # 输出本集总奖励
if render:
env.close() # 如果渲染标志为True,关闭环境
train_reinforce('CartPole-v1') # 开始训练
[Results] 运行结果
[Notice] 注意事项
深度Q网络(DQN)实现注释说明:
import
部分:导入所需的库,包括gym
(用于环境模拟)、torch
(用于深度学习)、random
和numpy
(用于随机数生成和数值计算)、deque
(用于经验回放缓冲区)。QNetwork
类:定义了Q网络的结构,包括输入层、隐藏层和输出层。DQNAgent
类:定义了DQN智能体,包括初始化、存储经验、选择动作和经验回放等方法。train_dqn
函数:主训练循环,包括环境交互、经验存储和训练。
** REINFORCE算法实现详细注释说明:**
- 导入库:-
gym
:用于创建和管理强化学习环境。-torch
和torch.nn
:用于构建和训练神经网络。-torch.optim
:用于优化神经网络参数。-numpy
:用于数值计算和数组操作。PolicyNetwork
类:- 定义了一个两层全连接的神经网络,输出动作的概率分布。- 使用ReLU激活函数和Softmax输出层。REINFORCEAgent
类:- 初始化策略网络和优化器。-select_action
方法基于策略网络输出的概率分布选择动作,并返回该动作和对应的对数概率。-update_policy
方法计算每个步骤的折扣奖励,并使用标准化后的折扣奖励更新策略网络的参数。train_reinforce
函数:- 初始化渲染标志render
。- 每训练100轮设置渲染标志为True。- 创建环境时,根据渲染标志设置render_mode
为"human"
或None
。- 在每一步中选择动作,执行动作,存储对数概率和奖励,更新状态,并在需要时渲染环境。- 在每个回合结束时,调用update_policy
更新策略网络。- 在渲染标志为True时,关闭环境以等待下次再打开。
文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者,或者关注VX公众号:**Rain21321,**联系作者。
版权归原作者 不去幼儿园 所有, 如有侵权,请联系我们删除。