【深度强化学习】(3) Policy Gradients 模型解析,附Pytorch完整代码
创始人
2024-06-01 07:22:37
0

大家好,今天和各位分享一下基于策略的深度强化学习方法,策略梯度法是对策略进行建模,然后通过梯度上升更新策略网络的参数。我们使用了 OpenAI 的 gym 库,基于策略梯度法完成了一个小游戏。完整代码可以从我的 GitHub 中获得:

https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Model


1. 基于策略的深度强化学习

针对智能体在大规模离散动作下无法建模的难题,在基于值函数的深度强化学习中,利用神经网络对 Q 值函数近似估计,使深度学习与强化学习得到完美融合。

但是基于值函数的深度强化学习有一定的不足之处:

(1) 无法处理连续动作的任务。DQN 系列的算法可以较好地解决强化学习中大规模离散动作空间的任务,但在连续动作的任务中,难以实现利用深度神经网络对所有状态-动作的 Q 值函数近似表达。

(2) 无法处理环境中状态受到限制的问题。在基于值函数深度强化学习更新网络参数时,损失函数会依赖当前状态和下一个状态的值函数,当智能体在环境中观察的状态有限或建模受到限制时,就会导致实际环境中两个不同的状态有相同的价值函数进而导致损失函数为零,出现梯度消失的问题。

(3) 智能体在环境中的探索性能较低。基于值函数的深度强化学习方法中,目标值都是从动作空间中选取一个最大价值的动作,导致智能体训练后的策略具有确定性,而面对一些需要随机策略进行探索的问题时,该方法就无法较好地解决。 

由于基于值函数的深度强化学习存在上述的一些局限性,需要新的方法来解决这些问题,于是基于策略的深度强化学习被提出。该方法中将智能体当前的策略参数化,并且使用梯度的方法进行更新。 


2. 策略梯度法

强化学习中策略梯度算法是对策略进行建模,然后通过梯度上升更新策略网络的参数。Policy Gradients 中无法使用策略的误差来构建损失函数,因为参数更新的目标是最大化累积奖励的期望值,所以策略更新的依据是某一动作对累积奖励的影响,即增加使累积回报变大的动作的概率,减弱使累积回报变小的动作的概率。 

下图代表智能体在当前策略下,完成一个回合后构成的状态、动作序列 r=\left \{ s_1,a_1,s_2,a_2,s_2,...s_T,a_T \right \},其中,Actor 是策略网络每个回合结束后的累计回报为每个状态下采取的动作的奖励之和

R = \sum_{t=1}^{T}r_t

智能体在环境中执行策略 \pi_ \theta 后状态转移概率

P_{\theta }(\tau )=P(s_1)P(r_1,s_2|s_1,a_1)\cdots P_\theta (a_T,s_T)P(r_{T+1},s_T|s_T,a_T)

P_{\theta }(\tau ) = \prod_{t=1}^{T} ( P_\theta (a_t|s_t) P(r_t,s_{t+1} | s_t,a_t) )

回合累计回报的期望

\bar{R}_\theta = \sum _{\tau } R(\tau ) P_\theta (\tau ) = E_{\tau \sim P_\theta (\tau )} [R(\tau )]

通过微分公式可以得到累计回报的梯度为:

\bigtriangledown \bar{R} _{\theta } = \sum_{\tau} R(\tau ) P_{\theta }(\tau) \bigtriangledown log P_\theta (\tau ) \approx \frac{1}{N} \sum_{n=1}^{N}\sum_{t=1}^{T} R(\tau ^n) \bigtriangledown log P_\theta (a_t^n | s_t^n)

利用累计回报的梯度更新策略网络的参数:

\theta ^ {new} \leftarrow \theta ^{old} + \beta \bigtriangledown \bar{R}_{\theta ^{old}}

其中, \beta 为梯度系数。通过上式的策略迭代可得,如果智能体在某个状态下采取的动作使累积回报增加,网络参数就会呈梯度上升趋势,该动作的概率就会增加,反之,梯度为下降趋势,减小该动作的概率。为了防止环境中所有的奖励都是正值,实现对于一些不好动作有一个负反馈,可以在总回报处减去一个基线。


3. 代码实现

策略函数 \pi (a|s) 是一个概率密度函数,用于控制智能体的运动。\pi (a|s)输入状态 s,输出每个动作 a 的概率分布。策略网络是指通过训练一个神经网络来近似策略函数。策略网络的参数 \theta 可通过策略梯度算法进行更新,从而实现对策略网络 \pi (a|s;\theta ) 的训练。 

伪代码如下

模型构建部分代码如下:

# 基于策略的学习方法,用于数值连续的问题
import numpy as np
import torch
from torch import nn
from torch.nn import functional as F# ----------------------------------------------------- #
#(1)构建训练网络
# ----------------------------------------------------- #
class Net(nn.Module):def __init__(self, n_states, n_hiddens, n_actions):super(Net, self).__init__()# 只有一层隐含层的网络self.fc1 = nn.Linear(n_states, n_hiddens)self.fc2 = nn.Linear(n_hiddens, n_actions)# 前向传播def forward(self, x):x = self.fc1(x)  # [b, states]==>[b, n_hiddens]x = F.relu(x)x = self.fc2(x)  # [b, n_hiddens]==>[b, n_actions]# 对batch中的每一行样本计算softmax,q值越大,概率越大x = F.softmax(x, dim=1)  # [b, n_actions]==>[b, n_actions]return x# ----------------------------------------------------- #
#(2)强化学习模型
# ----------------------------------------------------- #
class PolicyGradient:def __init__(self, n_states, n_hiddens, n_actions, learning_rate, gamma):# 属性分配self.n_states = n_states  # 状态数self.n_hiddens = n_hiddensself.n_actions = n_actions  # 动作数self.learning_rate = learning_rate  # 衰减self.gamma = gamma  # 折扣因子self._build_net()  # 构建网络模型# 网络构建def _build_net(self):# 网络实例化self.policy_net = Net(self.n_states, self.n_hiddens, self.n_actions)# 优化器self.optimizer = torch.optim.Adam(self.policy_net.parameters(), lr=self.learning_rate)# 动作选择,根据概率分布随机采样def take_action(self, state):  # 传入某个人的状态# numpy[n_states]-->[1,n_states]-->tensorstate = torch.Tensor(state[np.newaxis, :])# 获取每个人的各动作对应的概率[1,n_states]-->[1,n_actions]probs = self.policy_net(state)# 创建以probs为标准类型的数据分布action_dist = torch.distributions.Categorical(probs)# 以该概率分布随机抽样 [1,n_actions]-->[1] 每个状态取一组动作action = action_dist.sample()# 将tensor数据变成一个数 intaction = action.item()return action# 获取每个状态最大的state_valuedef max_q_value(self, state):# 维度变换[n_states]-->[1,n_states]state = torch.tensor(state, dtype=torch.float).view(1,-1)# 获取状态对应的每个动作的reward的最大值 [1,n_states]-->[1,n_actions]-->[1]-->floatmax_q = self.policy_net(state).max().item()return max_q# 训练模型def learn(self, transitions_dict):  # 输入batch组状态[b,n_states]# 取出该回合中所有的链信息state_list = transitions_dict['states']action_list = transitions_dict['actions']reward_list = transitions_dict['rewards']G = 0  # 记录该条链的returnself.optimizer.zero_grad()  # 优化器清0# 梯度上升最大化目标函数for i in reversed(range(len(reward_list))):# 获取每一步的reward, floatreward = reward_list[i]# 获取每一步的状态 [n_states]-->[1,n_states]state = torch.tensor(state_list[i], dtype=torch.float).view(1,-1)# 获取每一步的动作 [1]-->[1,1]action = torch.tensor(action_list[i]).view(1,-1)# 当前状态下的各个动作价值函数 [1,2]q_value = self.policy_net(state)# 获取已action对应的概率 [1,1]log_prob = torch.log(q_value.gather(1, action))# 计算当前状态的state_value = 及时奖励 + 下一时刻的state_valueG = reward + self.gamma * G# 计算每一步的损失函数loss = -log_prob * G# 反向传播loss.backward()# 梯度下降self.optimizer.step()

4. 实例演示

下面基于OpenAI 中的 gym 库,完成一个移动小车使得杆子竖直的游戏。状态states共包含 4 个,动作action有2个,向左和向右移动小车。迭代50回合,绘制每回合的 return 以及平均最大动作价值 q_max

代码如下:

import gym
import numpy as np
import matplotlib.pyplot as plt
from RL_brain import PolicyGradient# ------------------------------- #
# 模型参数设置
# ------------------------------- #n_hiddens = 16  # 隐含层个数
learning_rate = 2e-3  # 学习率
gamma = 0.9  # 折扣因子
return_list = []  # 保存每回合的reward
max_q_value = 0  # 初始的动作价值函数
max_q_value_list = []  # 保存每一step的动作价值函数# ------------------------------- #
#(1)加载环境
# ------------------------------- ## 连续性动作
env = gym.make("CartPole-v1", render_mode="human")
n_states = env.observation_space.shape[0]  # 状态数 4
n_actions = env.action_space.n  # 动作数 2# ------------------------------- #
#(2)模型实例化
# ------------------------------- #agent = PolicyGradient(n_states=n_states,  # 4n_hiddens=n_hiddens,  # 16n_actions=n_actions,  # 2learning_rate=learning_rate,  # 学习率gamma=gamma)  # 折扣因子# ------------------------------- #
#(3)训练
# ------------------------------- #for i in range(100):  # 训练10回合# 记录每个回合的returnepisode_return = 0# 存放状态transition_dict = {'states': [],'actions': [],'next_states': [],'rewards': [],'dones': [],}# 获取初始状态state = env.reset()[0]# 结束的标记done = False# 开始迭代while not done:# 动作选择action = agent.take_action(state)  # 对某一状态采取动作# 动作价值函数,曲线平滑max_q_value = agent.max_q_value(state) * 0.005 + max_q_value * 0.995# 保存每一step的动作价值函数max_q_value_list.append(max_q_value)# 环境更新next_state, reward, done, _, _ = env.step(action)# 保存每个回合的所有信息transition_dict['states'].append(state)transition_dict['actions'].append(action)transition_dict['next_states'].append(next_state)transition_dict['rewards'].append(reward)transition_dict['dones'].append(done)# 状态更新state = next_state# 记录每个回合的returnepisode_return += reward# 保存每个回合的returnreturn_list.append(episode_return)# 一整个回合走完了再训练模型agent.learn(transition_dict)# 打印回合信息print(f'iter:{i}, return:{np.mean(return_list[-10:])}')# 关闭动画
env.close()# -------------------------------------- #
# 绘图
# -------------------------------------- #plt.subplot(121)
plt.plot(return_list)
plt.title('return')
plt.subplot(122)
plt.plot(max_q_value_list)
plt.title('max_q_value')
plt.show()

左图代表每回合的return,右图为平均最大动作价值

相关内容

热门资讯

Python|位运算|数组|动... 目录 1、只出现一次的数字(位运算,数组) 示例 选项代...
张岱的人物生平 张岱的人物生平张岱(414年-484年),字景山,吴郡吴县(今江苏苏州)人。南朝齐大臣。祖父张敞,东...
西游西后传演员女人物 西游西后传演员女人物西游西后传演员女人物 孙悟空 六小龄童 唐僧 徐少华 ...
名人故事中贾岛作诗内容简介 名人故事中贾岛作诗内容简介有一次,贾岛骑驴闯了官道.他正琢磨着一句诗,名叫《题李凝幽居》全诗如下:闲...
和男朋友一起优秀的文案? 和男朋友一起优秀的文案?1.希望是惟一所有的人都共同享有的好处;一无所有的人,仍拥有希望。2.生活,...
戴玉手镯的好处 戴玉手镯好还是... 戴玉手镯的好处 戴玉手镯好还是碧玺好 女人戴玉?戴玉好还是碧玺好点佩戴手镯,以和田玉手镯为佳!相嫌滑...
依然什么意思? 依然什么意思?依然(汉语词语)依然,汉语词汇。拼音:yī    rán基本解释:副词,指照往常、依旧...
高尔基的散文诗 高尔基的散文诗《海燕》、《大学》、《母亲》、《童年》这些都是比较出名的一些代表作。
心在飞扬作者简介 心在飞扬作者简介心在飞扬作者简介如下。根据相关公开资料查询,心在飞扬是一位优秀的小说作者,他的小说作...
卡什坦卡的故事赏析? 卡什坦卡的故事赏析?讲了一只小狗的故事, 我也是近来才读到这篇小说. 作家对动物的拟人描写真是惟妙...
林绍涛为简艾拿绿豆糕是哪一集 林绍涛为简艾拿绿豆糕是哪一集第三十二集。 贾宽认为是阎帅间接导致刘映霞住了院,第二天上班,他按捺不...
小爱同学是女生吗小安同学什么意... 小爱同学是女生吗小安同学什么意思 小爱同学,小安同学说你是女生。小安是男的。
内分泌失调导致脸上长斑,怎么调... 内分泌失调导致脸上长斑,怎么调理内分泌失调导致脸上长斑,怎么调理先调理内分泌,去看中医吧,另外用好的...
《魔幻仙境》刺客,骑士人物属性... 《魔幻仙境》刺客,骑士人物属性加点魔幻仙境骑士2功1体质
很喜欢她,该怎么办? 很喜欢她,该怎么办?太冷静了!! 太理智了!爱情是需要冲劲的~不要考虑着考虑那~否则缘...
言情小说作家 言情小说作家我比较喜欢匪我思存的,很虐,很悲,还有梅子黄时雨,笙离,叶萱,还有安宁的《温暖的玄》 小...
两个以名人的名字命名的风景名胜... 两个以名人的名字命名的风景名胜?快太白楼,李白。尚志公园,赵尚志。
幼儿教育的代表人物及其著作 幼儿教育的代表人物及其著作卡尔威特的《卡尔威特的教育》,小卡尔威特,他儿子成了天才后写的《小卡尔威特...
海贼王中为什么说路飞打凯多靠霸... 海贼王中为什么说路飞打凯多靠霸气升级?凯多是靠霸气升级吗?因为之前刚到时确实打不过人家因为路飞的实力...
运气不好拜财神有用吗运气不好拜... 运气不好拜财神有用吗运气不好拜财神有没有用1、运气不好拜财神有用。2、拜财神上香前先点蜡烛,照亮人神...