上面讲了DQN的类的实现, 下面还有CnnDQN, 这个类是针对另外一个gym项目做的, “PongNoFrameskip-v4”,截图为:
重新定义了一个 CnnDQN 类:
class CnnDQN(nn.Module):
def __init__(self, input_shape, num_actions):
super(CnnDQN, self).__init__()
self.input_shape = input_shape
self.num_actions = num_actions
self.features = 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()
)
self.fc = nn.Sequential(
nn.Linear(self.feature_size(), 512),
nn.ReLU(),
nn.Linear(512, self.num_actions)
)
def forward(self, x):
x = self.features(x)
x = x.view(x.size(0), -1)
x = self.fc(x)
return x
def feature_size(self):
return self.features(autograd.Variable(torch.zeros(1, *self.input_shape))).view(1, -1).size(1)
def act(self, state, epsilon):
if random.random() > epsilon:
with torch.no_grad():
state = Variable(torch.FloatTensor(np.float32(state)).unsqueeze(0))
q_value = self.forward(state)
action = q_value.max(1)[1].data[0]
else:
action = random.randrange(env.action_space.n)
return action
和上面DQN不同的是,这里的网络定义为 self.features 和 self.fc:
self.features = 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()
)
self.fc = nn.Sequential(
nn.Linear(self.feature_size(), 512),
nn.ReLU(),
nn.Linear(512, self.num_actions)
)
nn.Conv2d是卷积的意思,引入卷积做为特征抽取,怎么理解呢,感觉就是从多个角度看待问题。
然后训练也有所不同,不过还是和DQN非常相似, 就是构造一个 optimizer 优化器,然后丢到 compute_td_loss 中去优化网络层的参数。
还有就是,fc 应该是 full connection 的简写, 也就是学术上常常提到的全连接层,先不管,我们知道作者大概就是想构建一个全连接层。
说到学术, 其实 Conv2d, ReLU, Linear这些在学术上面,叫 算子。
后面也好像没得啥子好说的,如果要说,就要从神经网络的组成上来分析一下,但是我也不太擅长这个,我先查查资料,看看能不能帮大家整理一下。
参考: