【问题标题】:How to properly optimize shared network between actor and critic?如何正确优化演员和评论家之间的共享网络?
【发布时间】:2019-09-12 17:03:41
【问题描述】:

我正在构建一个演员批评强化学习算法来解决环境问题。我想使用单个编码器来查找我的环境的表示。

当我与演员和评论家共享编码器时,我的网络没有学习任何东西:

class Encoder(nn.Module):
  def __init__(self, state_dim):
    super(Encoder, self).__init__()

    self.l1 = nn.Linear(state_dim, 512)

  def forward(self, state):
    a = F.relu(self.l1(state))
    return a

class Actor(nn.Module):
  def __init__(self, state_dim, action_dim, max_action):
    super(Actor, self).__init__()

    self.l1 = nn.Linear(state_dim, 128)
    self.l3 = nn.Linear(128, action_dim)

    self.max_action = max_action

  def forward(self, state):
    a = F.relu(self.l1(state))
    # a = F.relu(self.l2(a))
    a = torch.tanh(self.l3(a)) * self.max_action
    return a

class Critic(nn.Module):
  def __init__(self, state_dim, action_dim):
    super(Critic, self).__init__()

    self.l1 = nn.Linear(state_dim + action_dim, 128)
    self.l3 = nn.Linear(128, 1)

  def forward(self, state, action):
    state_action = torch.cat([state, action], 1)

    q = F.relu(self.l1(state_action))
    # q = F.relu(self.l2(q))
    q = self.l3(q)
    return q

但是,当我为演员使用不同的编码器并为评论家使用不同的编码器时,它会正确学习。

class Actor(nn.Module):
def __init__(self, state_dim, action_dim, max_action):
    super(Actor, self).__init__()

    self.l1 = nn.Linear(state_dim, 400)
    self.l2 = nn.Linear(400, 300)
    self.l3 = nn.Linear(300, action_dim)

    self.max_action = max_action

def forward(self, state):
    a = F.relu(self.l1(state))
    a = F.relu(self.l2(a))
    a = torch.tanh(self.l3(a)) * self.max_action
    return a

class Critic(nn.Module):
  def __init__(self, state_dim, action_dim):
    super(Critic, self).__init__()

    self.l1 = nn.Linear(state_dim + action_dim, 400)
    self.l2 = nn.Linear(400, 300)
    self.l3 = nn.Linear(300, 1)

  def forward(self, state, action):
    state_action = torch.cat([state, action], 1)

    q = F.relu(self.l1(state_action))
    q = F.relu(self.l2(q))
    q = self.l3(q)
    return q

我很确定它是因为优化器。 在共享编码器代码中,我将其定义为傻瓜:

self.actor_optimizer = optim.Adam(list(self.actor.parameters())+
                                      list(self.encoder.parameters()))
self.critic_optimizer = optim.Adam(list(self.critic.parameters()))
                                         +list(self.encoder.parameters()))

在单独的编码器中,它只是:

self.actor_optimizer = optim.Adam((self.actor.parameters()))
self.critic_optimizer = optim.Adam((self.critic.parameters()))

两个优化器必须是因为actorcritic算法。

如何结合两个优化器来正确优化编码器?

【问题讨论】:

    标签: python optimization neural-network pytorch reinforcement-learning


    【解决方案1】:

    我不确定你是如何共享编码器的。

    但是,我建议您创建一个编码器实例并将其传递给演员和评论家

    encoder_net = Encoder(state_dim)
    actor = Actor(encoder_net, state_dim, action_dim, max_action)
    critic = Critic(encoder_net, state_dim)
    

    在前向传递期间,首先将状态批次先通过编码器,然后再通过网络的其余部分,例如:

    class Encoder(nn.Module):
        def __init__(self, state_dim):
            super(Encoder, self).__init__()
    
            self.l1 = nn.Linear(state_dim, 512)
    
        def forward(self, state):
            a = F.relu(self.l1(state))
            return a
    
    class Actor(nn.Module):
        def __init__(self, encoder, state_dim, action_dim, max_action):
            super(Actor, self).__init__()
            self.encoder = encoder
    
            self.l1 = nn.Linear(512, 128)
            self.l3 = nn.Linear(128, action_dim)
    
            self.max_action = max_action
    
        def forward(self, state):
            state = self.encoder(state)
            a = F.relu(self.l1(state))
            # a = F.relu(self.l2(a))
            a = torch.tanh(self.l3(a)) * self.max_action
            return a
    
    class Critic(nn.Module):
        def __init__(self, encoder, state_dim):
            super(Critic, self).__init__()
            self.encoder = encoder
    
            self.l1 = nn.Linear(512, 128)
            self.l3 = nn.Linear(128, 1)
    
        def forward(self, state):
            state = self.encoder(state)
    
            q = F.relu(self.l1(state))
            # q = F.relu(self.l2(q))
            q = self.l3(q)
            return q
    

    注意:critic 网络现在是状态值函数 V(s) 的函数逼近器,而不是状态-动作值函数 Q(s,a)。

    使用此实现,您可以在不将编码器参数传递给优化器的情况下执行优化,如下所示:

    self.actor_optimizer = optim.Adam((self.actor.parameters()))
    self.critic_optimizer = optim.Adam((self.critic.parameters()))
    

    因为编码器参数现在在两个网络之间共享。

    希望这会有所帮助! :)

    【讨论】:

    • 谢谢。我做了,它不起作用,两个优化器以冲突的方式更改编码器参数,他们没有一起学习。
    猜你喜欢
    • 1970-01-01
    • 2016-10-20
    • 2013-01-15
    • 2019-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    相关资源
    最近更新 更多