python - 组合的 GRU 和 CNN 网络总是为所有输入返回相同的值
问题描述
我正在尝试训练一个组合的 CNN 和 GRU/LSTM,以找出一系列移动图片中的对象数量和不移动的对象数量。出于这个原因,我使用 CNN 来处理我的图像并因此使用 GRU。我的问题是 GRU 总是为每个输入集返回相同的值。这可能是什么原因?
我已经尝试使用不同的学习率并在 GRU 之后添加线性层。
我的网络:
class GRU(nn.Module):
def __init__(self, **kwargs):
super(GRU, self).__init__()
self.n_class = int(kwargs.get("n_class"))
self.seq_length = int(kwargs.get("seq_length"))
self.input_shape = int(kwargs.get("input_shape"))
self.n_channels = int(kwargs.get("n_channels"))
self.conv1 = nn.Conv2d(in_channels=1 * seq_length, out_channels=4 * seq_length, kernel_size=5)
self.conv2 = nn.Conv2d(in_channels=4 * seq_length, out_channels=8 * seq_length, kernel_size=5)
self.conv3 = nn.Conv2d(in_channels=8 * seq_length, out_channels=16 * seq_length, kernel_size=5)
self.rnn = nn.GRU(
input_size=self.seq_length,
hidden_size=64,
num_layers=1,
batch_first=True)
self.linear = nn.Linear(64, 2)
def forward(self, t):
t = self.conv1(t)
t = F.relu(t)
t = F.max_pool2d(t, kernel_size=2, stride=2)
# second conv layer
t = self.conv2(t)
t = F.relu(t)
t = F.max_pool2d(t, kernel_size=4, stride=4)
# third conv layer
t = self.conv3(t)
t = F.relu(t)
t = F.max_pool2d(t, kernel_size=3, stride=3)
t = t.reshape(-1 , self.seq_length, 16 * 20 ** 2)
t = t.permute(0,2,1)
t, (h_n) =self.rnn(t)
t = self.linear(t[:,-1])
return t
这是我的训练:
for epoch in range(number_epochs):
for batch in get_batch_generator(batch_size, rootdir, seq_length=seq_length):
current_batch = batch[0].cuda()
current_labels = batch[1].cuda()
pre = nw(current_batch)
loss_func = torch.nn.MSELoss()
loss = loss_func(pre, current_labels)
loss.backward()
optimizer = optim.Adam(nw.parameters(), lr=learning_rate)
optimizer.step()
这是输出的示例,实际标签:
tensor([[ 4., 5.],
[10., 0.],
[10., 0.],
[ 2., 9.],
[ 5., 1.],
[10., 0.]], device='cuda:0')
我的网络预测:
tensor([[2.0280, 1.1517],
[2.0175, 1.1593],
[2.0323, 1.1434],
[2.0333, 1.1557],
[2.0200, 1.1546],
[2.0069, 1.1687]], device='cuda:0', grad_fn=<AddmmBackward>)
因此,对于这两个类,两个类(移动和不移动对象)的输出是相同的,但情况并非如此。
解决方案
最后我发现有必要将每批的梯度设置为零。由于某种原因,当我在没有 LSTM 的情况下训练普通 CNN 时,这并没有引起问题。在反向传播之前需要在每个训练循环中添加的命令:
optimizer.zero_grad()
或者
nw.zero_grad()
推荐阅读
- swift - iOS14中表格部分标题中的白色背景
- python-3.x - python opencv试图用矩方法找到轮廓中心
- c++ - long long int 不支持大数的乘法
- sql - 查询1500万行,用node js处理
- python - AWS EKS 中使用 KubernetesExecutor 的 Apache Airflow 没有日志
- wso2 - 在 WSO2 EI 客户端信任库中续订证书
- python - Python - 父方法不访问变量子项的值
- python - 如何将 PyTorch 张量分块成具有重叠的指定桶大小?
- spring - 在引导配置之间共享属性
- autodesk-forge - Forge:尝试 GetPublishJob 时偶尔出现 403