书中知识
3.5 蒙特卡洛方法

统计每一个状态s出现的总次数和总回报,用大数定律,总回报/总次数≈状态s的期望回报
第4章 动态规划算法
策略迭代中的策略评估使用贝尔曼期望方程来得到一个策略的状态价值函数,这是一个动 态规划的过程;而价值迭代直接使用贝尔曼最优方程来进行动态规划,得到最终的最优状态价值函数。
基于动态规划的这两种强化学习算法要求事先知道环境的状态转移函数和奖励函数,也就是需要知道整个马尔可夫决策过程。在这样一个白盒环境中,不需要通过智能体和环境的大量交互来学习,可以直接用动态规划求解状态价值函数。但是现实中的白盒环境很少,这也是动态规划算法的局限之处,我们无法将其运用到很多实际场景中。
动态规划不是使用的时序差分思想,计算每一个状态S的最大Q作为下一个动作,当误差最大的那个状态S的误差小于阙值时停止。因为要计算所有状态 s 下的所有 Q(s,a)价值,所以需要对全部状态迭代多次完成收敛
策略迭代是策略评估和策略提升不断循环交替,直至最后得到最优策略的过程
1. 策略评估
2. 策略提升

如果只在策略评估中进行一轮价值更新,然后直接根据更新后的价值进行策略提升, 这样是否可以呢?答案是肯定的,这其实就是本节将要讲解的价值迭代算法,它可以被认为是 一种策略评估只进行了一轮更新的策略迭代算法。
价值迭代
1. 如果只在策略评估中进行一轮价值更新,然后直接根据更新后的价值进行策略提升, 这样是否可以呢?答案是肯定的,这其实就是本节将要讲解的价值迭代算法,它可以被认为是 一种策略评估只进行了一轮更新的策略迭代算法


5.3 Sarsa算法
Q_table记录每一个表格位置的所有动作价值,初始值都等于0
根据公式计算Q(S,a),状态和动作必须配对,更新Q是更新的Q(S,a),不同Q(S,a)对应迭代公式中不同动作a的值

5.4 多步Sarsa算法
多步时序差分的意思是使用n步的奖励,然后使用之后状态的价值估计

当前在s,当采集够n步(s,a,r,s',a')时,计算一次当前s的Q_table

5.5 Q-learning 算法
用S‘最大Q的动作a所在状态作为目标值,取未来状态的最大Q值,不依赖当前策略的动作选择
![]()

后面计算的时候取所有动作中的maxQ作为目标target,而Sarsa是(s,a)匹配的
Sarsa和Q-learing区别
Sarsa更保守而Q-learing更激进,因为前者会考虑不利动作的风险,而后者只盲目选择最大Q的动作,不考虑会以epsilon概率选择其他动作的风险,在悬崖漫步问题中,Q-learing绕远会降低收益,而紧靠悬崖走收益最大,而Sarsa会考虑到掉进悬崖的风险。
第7章 QDN算法
DQN算法便可以用来解决连续状态下离散动作的问题
通常DQN(以及 Q-learning)只能处理动作离散的情况,因为在函数Q 的更新过程中有maxa这一操作
代码错误
env.seed(0)改为env.reset(seed=0)
state = env.reset()改为state = env.reset()[0]
next_state, reward, done, _ = env.step(action)改为next_state, reward, done, _ ,_ = env.step(action)
Gym环境
现在的env.step(action)返回5个参数

代码实践
gym安装0.25.2版本后继续使用'CartPole-v0'版本
卸载原有gym:pip uninstall gym
安装特定版本:pip install gym==0.25.2
第10章-Actor-Critic算法
self.actor_optimizer = torch.optim.Adam(self.actor.parameters(), lr=actor_lr)
1. torch.optim 是 PyTorch 提供的一个用于实现各种优化算法的模块,它包含了众多常见的优化器,例如 SGD(随机梯度下降)、Adam、RMSprop 等。这些优化器的核心功能是根据计算得到的梯度,对神经网络模型的参数进行更新,以此来最小化损失函数。
2. Adam(Adaptive Moment Estimation)是一种自适应学习率的优化算法,它结合了 AdaGrad 和 RMSProp 的优点,能够自适应地调整每个参数的学习率。Adam 优化器在很多深度学习任务中都表现出色,因为它可以在训练过程中自动调整学习率,避免学习率过大或者过小的问题。
3. self.actor是一个继承自 torch.nn.Module 的神经网络模型实例,self.actor.parameters() 是一个生成器,返回 self.actor 模型中所有需要学习的参数。这些参数就是优化器要更新的对象。例如,在一个全连接神经网络中,这些参数可能包括权重(weights)和偏置(biases)。
import gym
import torch
import torch.nn.functional as F
import numpy as np
import matplotlib.pyplot as plt
import rl_utils
class PolicyNet(torch.nn.Module):
def __init__(self, state_dim, hidden_dim, action_dim):
super(PolicyNet, self).__init__()
self.fc1 = torch.nn.Linear(state_dim, hidden_dim)
self.fc2 = torch.nn.Linear(hidden_dim, action_dim)
def forward(self, x):
x = F.relu(self.fc1(x))
return F.softmax(self.fc2(x), dim=1)
class ValueNet(torch.nn.Module):
def __init__(self, state_dim, hidden_dim):
super(ValueNet, self).__init__()
self.fc1 = torch.nn.Linear(state_dim, hidden_dim)
self.fc2 = torch.nn.Linear(hidden_dim, 1)
def forward(self, x):
x = F.relu(self.fc1(x))
return self.fc2(x)
class ActorCritic:
def __init__(self, state_dim, hidden_dim, action_dim, actor_lr, critic_lr,
gamma, device):
# 策略网络
self.actor = PolicyNet(state_dim, hidden_dim, action_dim).to(device)
self.critic = ValueNet(state_dim, hidden_dim).to(device) # 价值网络
# 策略网络优化器
self.actor_optimizer = torch.optim.Adam(self.actor.parameters(),
lr=actor_lr)
self.critic_optimizer = torch.optim.Adam(self.critic.parameters(),
lr=critic_lr) # 价值网络优化器
self.gamma = gamma
self.device = device
def take_action(self, state):
state = torch.tensor([state], dtype=torch.float).to(self.device)
probs = self.actor(state)
action_dist = torch.distributions.Categorical(probs)
action = action_dist.sample()
return action.item()
def update(self, transition_dict):
states = torch.tensor(transition_dict['states'],
dtype=torch.float).to(self.device)
actions = torch.tensor(transition_dict['actions']).view(-1, 1).to(
self.device)
rewards = torch.tensor(transition_dict['rewards'],
dtype=torch.float).view(-1, 1).to(self.device)
next_states = torch.tensor(transition_dict['next_states'],
dtype=torch.float).to(self.device)
dones = torch.tensor(transition_dict['dones'],
dtype=torch.float).view(-1, 1).to(self.device)
# 时序差分目标
td_target = rewards + self.gamma * self.critic(next_states) * (1 -
dones)
td_delta = td_target - self.critic(states) # 时序差分误差
log_probs = torch.log(self.actor(states).gather(1, actions))
actor_loss = torch.mean(-log_probs * td_delta.detach())
# 均方误差损失函数
# 将 td_target张量从计算图中分离出来得到一个新的张量,这个新张量和原张量具有相同的数据,但在反向传播时不会对其进行梯度计算
critic_loss = torch.mean(F.mse_loss(self.critic(states), td_target.detach()))
self.actor_optimizer.zero_grad()
self.critic_optimizer.zero_grad()
actor_loss.backward() # 计算策略网络的梯度
critic_loss.backward() # 计算价值网络的梯度
self.actor_optimizer.step() # 更新策略网络的参数
self.critic_optimizer.step() # 更新价值网络的参数
actor_lr = 1e-3
critic_lr = 1e-2
num_episodes = 1000
hidden_dim = 128
gamma = 0.98
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
print(device)
env_name = 'CartPole-v0'
# env = gym.make(env_name, render_mode = "human") # 可视化窗口
env = gym.make(env_name)
env.seed(0)
# 为 PyTorch 库设置随机种子,将 PyTorch 中的随机数生成器的初始状态固定为 0
torch.manual_seed(0)
# 观测空间是一个包含 4 个浮点数的一维数组,分别表示小车的位置、小车的速度、杆子的角度以及杆子的角速度
state_dim = env.observation_space.shape[0]
action_dim = env.action_space.n
agent = ActorCritic(state_dim, hidden_dim, action_dim, actor_lr, critic_lr, gamma, device)
return_list = rl_utils.train_on_policy_agent(env, agent, num_episodes)
# 奖励数据可视化
episodes_list = list(range(len(return_list)))
plt.plot(episodes_list, return_list)
plt.xlabel('Episodes')
plt.ylabel('Returns')
plt.title('Actor-Critic on {}'.format(env_name))
plt.show()
mv_return = rl_utils.moving_average(return_list, 9)
plt.plot(episodes_list, mv_return)
plt.xlabel('Episodes')
plt.ylabel('Returns')
plt.title('Actor-Critic on {}'.format(env_name))
plt.show()


420

被折叠的 条评论
为什么被折叠?



