蒙特卡洛策略梯度(REINFORCE算法)及其改进

蒙特卡洛策略梯度(REINFORCE算法)

回顾

策略梯度中的梯度等于:某一状态下采取某一动作的对数概率乘以一个权重。而这个权重就是回合中的奖励值。
在这里插入图片描述

蒙特卡洛策略梯度:REINFORCE

蒙特卡洛算法的核心就是智能体与环境必须完成一个完整的Episode交互。当智能体完成一个Episode后,再利用获得的数据(或轨迹)进行智能体参数 θ \theta θ的更新。即一个Episode,参数更新一次

根据轨迹数据,可以计算出每一步骤之后未来总奖励 G t G_{t} Gt G 1 G_{1} G1表示从第一步往后所能得到的未来总奖励; G 2 G_{2} G2表示从第二步往后所能得到的未来总奖励;依次类推。

计算每一步未来总奖励 G t G_{t} Gt

在训练中可以用列表来依次存储state,action 和reward,具体代码可以表示为:

class Agent():
    def __init__(self, state_dim, action_dim):
    	....其他参数
        self.episode_s = []
        self.episode_a = []
        self.episode_r  = []
    def store(self, state, action, reward): # 保留回合中的数据
        self.episode_s.append(state)
        self.episode_a.append(action)
        self.episode_r.append(reward)
    def learn(self):
    	# 计算从每一个时刻开始,到回合结束所得到的折扣奖励
        G = []
        g = 0
        for r in self.episode_r[::-1]:
            g = self.gamma * g + r
            G.insert(0,g)
计算动作概率
class Policy(nn.Module):
    def __init__(self, s_dim, a_dim, h_dim):
        super(Policy, self).__init__()
        self.s_dim = s_dim
        self.a_dim = a_dim
        self.h_dim = h_dim
        self.fc1 = nn.Linear(self.s_dim, self.h_dim)
        self.fc2 = nn.Linear(self.h_dim, self.a_dim)
    def forward(self, state):
        s = F.relu(self.fc1(state))
        a_prob = F.softmax(self.fc2(s),dim=1)
        return a_prob
交互过程中,选择动作
def choose_action(self, state,deterministic):
    state = torch.tensor(state,dtype=torch.float).to(device)
    state = torch.unsqueeze(state,dim=0)  
    a_prob = self.policy(state).cpu().data.numpy().flatten()
    if deterministic:
        a = np.argmax(a_prob)
    else:
        a = np.random.choice(range(self.a_dim),p=a_prob)
    return a
策略更新

策略的loss就是每一步未来总奖励乘以相应动作的对数概率。

def learn(self):
    	# 计算从每一个时刻开始,到回合结束所得到的折扣奖励
        G = []
        g = 0
        for r in self.episode_r[::-1]:
            g = self.gamma * g + r
            G.insert(0,g)
            
        for i,s in enumerate(self.episode_s):
            state = torch.unsqueeze(torch.tensor(s,dtype=torch.float),dim=0).to(device)
            a = self.episode_a[i]
            a_prob = self.policy(state).flatten() # 展开
            g = G[i]
            #loss = - g * torch.log(a_prob[a]) # loss1
            loss = - pow(self.gamma, i) * g * torch.log(a_prob[a])# loss2
            # 测试结果显示,loss的收敛效果会更好。第一种方差很大。
            self.policy_optim.zero_grad()
            loss.backward()
            self.policy_optim.step()

蒙特卡洛策略梯度:REINFORCE,使用baseline

在这里插入图片描述

当使用baseline策略时,我们需要使用网络计算b。故多增加一个网络

class Value(nn.Module):
    def __init__(self, state_dim, hidden_width):
        super(Value, self).__init__()
        self.fc1 = nn.Linear(state_dim, hidden_width)
        self.fc2 = nn.Linear(hidden_width, 1)

    def forward(self, s):
        s = F.relu(self.fc1(s))
        v_s = self.fc2(s)
        return v_s
策略更新
def learn(self):
    G = []
    g = 0
    for r in self.episode_r[::-1]:
        g = self.gamma * g + r
        G.insert(0,g) # 在列表的index=0的位置插入元素g

    for i,s in enumerate(self.episode_s):
        state = torch.unsqueeze(torch.tensor(s,dtype=torch.float),dim=0).to(device)
        a = self.episode_a[i]
        a_prob = self.policy(state).flatten() # 展开
        g = G[i]
        v_s = self.value(state).flatten()
        # policy_loss = - pow(self.gamma, i) * (g-v_s.detach()) * torch.log(a_prob[a])
        policy_loss = - (g - v_s.detach()) * torch.log(a_prob[a])

        self.policy_optim.zero_grad()
        policy_loss.backward()
        self.policy_optim.step()

        value_loss = (g-v_s)**2
        self.value_optim.zero_grad()
        value_loss.backward()
        self.value_optim.step()
    self.episode_s, self.episode_a, self.episode_r = [],[],[] # 一个回合的数据只能用一次

注意

蒙特卡洛策略梯度算法,每一个回合的数据只能用一次。用完就扔掉。

使用时序差分方法

  • 蒙特卡洛方法的智能体每次都要走完一个Episode后,参数才能开始更新,更新频率比较慢。
  • 而时序差分方法的更新频率更高。该方法是使用 Q ( s , a ) Q(s,a) Q(s,a)来近似代替REINFORCE算法中的 G t G_{t} Gt

在这里插入图片描述

参考

https://github.com/Lizhi-sjtu/DRL-code-pytorch/tree/main/1.REINFORCE

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值