Pytorch - 使用或不使用批次实现相同的训练

问题描述 投票:0回答:1

我在 PyTorch 中有一个模型,在使用标准训练过程时,它可以很好地收敛于参考示例,其中优化器同时对所有样本进行训练:

loss = loss_fnc(samples)

model.optim.zero_grad()
loss.backward()
model.optim.step()

现在模型应该训练更多的内存密集型任务(更多的样本,更大的输入大小),所以我认为这将有助于批量训练。为此,我使用了这个非常标准的方法和 for 循环:

loss_sum = 0

for k_batch in range(0, len(samples), batch_size):

    samples_batch = samples[k_batch:k_batch + batch_size]

    loss = loss_fnc(samples_batch)
    loss_sum += loss*len(samples_batch)

    model.optim.zero_grad()
    loss.backward()

    model.optim.step()

loss_comp = loss_sum/len(samples)

现在,当我跳过此方法中的训练部分并仅计算损失时,得到的

loss_comp
与一次计算所有样本时的结果相同(如上面的方法)。当然,通过批量训练,
loss_comp
会有所不同,因为模型在整个批次中都会发生变化。

现在我面临的问题是,在使用批量训练时,模型不再收敛于我的参考示例。在这两种情况下,样本在训练之前就已随机排序。

由于我只对减少计算所需的内存需求感兴趣,因此在尝试其他任何操作之前,有没有办法在使用批量而不是“一次性”时真正进行相同的训练?我尝试更改函数,以便只批量计算损失,并在最后完成优化步骤,但我似乎没有让它发挥作用。

据我了解,使用 DataLoader 不会改变与此行为有关的任何内容。

python pytorch neural-network
1个回答
0
投票

我想我找到了一个非常简单的解决方案。我再次尝试了这种方法,总结了批量计算期间的损失,但最后只训练了一次。之前,我一定在丢失数据类型方面做错了什么,所以我现在用第一批丢失来初始化它,以确保正确的类型:

for k_batch in range(0, len(samples), batch_size):

    samples_batch = samples[k_batch:k_batch + batch_size]

    loss = loss_fnc(samples_batch)
    if k_batch == 0:
        loss_sum = loss*len(samples_batch)
    else:
        loss_sum += loss*len(samples_batch)

loss = loss_sum/len(samples)

model.optim.zero_grad()
loss.backward()
model.optim.step()

当我现在将损失与参考

loss
(来自“一次性”训练)进行比较时,值是相等的。作为梯度函数,参考
loss
具有
MseLossBackward0
,而这些批次新计算的损失具有
DivBackward0
。尽管如此,无论是否使用批次,以下训练似乎都是相同的。

© www.soinside.com 2019 - 2024. All rights reserved.