A2C实现要点
A2C也是属于Policy算法族的,是在Policy Gradient的基础上拆分出两个网络Critic和Actor。代码实现有如下要点:
网络
- actor网络:输入state,输出动作的概率分布,从中选择动作后作为critic网络的输入
- critic网络:输入state和action预估下一个state的q-value
损失函数
- actor网络:在Policy Gradient损失函数的Q-value值上减一个Baseline使得反馈有正有负,减少网络的波动。
- critic网络:用于预估state的Q-value, loss为"真实值"和预估值的误差,而"真实值"是用Bellman方程求得,即Q(s) = r + gamma*Q(s’),和DQN的实现相似
算法实现
构建网络
actor和critic网络的输入都有state,只是输出不同所以可以放入同一个主体网络中训练共享信息和参数,但各自的输出层不同。网络代码如下:
# 构建model,model的主体一致,但输出层不同,会同时输出policy和Q-value
class A2CModel(nn.Module):
def __init__(self, input_shape, n_actions):
super().__init__()
self.conv = nn.Sequential(
nn.Conv2d(input_shape[0], 32, kernel_size=8, stride=4),
nn.ReLU(),
nn.Conv2d(32, 64, kernel_size=4, stride=2),
nn.ReLU(),
nn.Conv2d(64, 64, kernel_size=3, stride=1),
nn.ReLU()
)
conv_out_size = self._get_conv_out(input_shape)
# 用于输出策略(动作的概率分布)
self.policy = nn.Sequential(
nn.Linear(conv_out_size, 512),
nn.ReLU(),
nn.Linear(512, n_actions)
)
# 输出预估的value
self.value = nn.Sequential(
nn.Linear(conv_out_size, 512),
nn.ReLU(),
nn.Linear(512, 1)
)
def _get_conv_out(self, shape):
o = self.conv(torch.zeros(1, *shape))
return int(np.prod(o.size()))
def forward(self, x):
fx = x.float() / 256
conv_out = self.conv(fx).view(fx.size()[0], -1)
return self.policy(conv_out), self.value(conv_out)
构建environment和agent
(在构建agent以及后续的experience source时用到了高级包PTAN, 详情请参见深度强化学习高级包PTAN-1. Agent, Experience
)
- 为了加速训练进程可以多个环境并行运行
- 使用PolicyAgent
NUM_ENVS = 70
make_env = lambda: ptan.common