常见问题

    不要在训练循环中累积历史记录。默认情况下,当计算涉及到有需要梯度的变量时,此计算过程将保留运算的历史记录。这意味着您应该避免在计算中使用这些变量,这些变量的生存期将超出您的训练循环(例如在跟踪统计数据时)。您应该分离该变量或访问其底层数据。

    有时,当可微分变量可能发生时,它可能并不明显。考虑以下训练循环(从源代码节选):

    在本例中,由于 loss 是具有 autograd 历史记录的可微分变量,所以 total_loss 将在整个训练循环中累积历史记录。你可以替换成 total_loss + = float(loss) 来解决这个问题。

    这个问题的另一个例子:

    作用域的范围可能比你想象的要大。例如:

    在本段代码中,即使当 h 在执行时,intermediate 仍然存在,因为它的作用域延伸出了循环的末尾。为了尽早释放它,当你不需要它时,你应该用 del intermediate 删除这个中间值。

    不要在太大的序列上运行 RNN。 因为 RNN 反向传播所需的内存量与 RNN 的长度成线性关系;因此,如果尝试向 RNN 提供一个太长的序列时,会耗尽内存。

    这一现象的技术术语是时间反向传播Backpropagation through time,关于如何实现截断的 BPTT 有很多参考资料,包括在单词语言模型 中;截断由这个论坛帖子中描述的 repackage 函数处理。

    PyTorch 使用缓存内存分配器来加速内存分配。因此,nvidia-smi 中显示的值通常不会反映真实的内存使用情况。有关 GPU 内存管理的更多细节,请参阅 。

    如果您的 GPU 内存在 Python 退出后仍未释放,那么很可能某些 Python 子进程仍然存在。你可以通过 ps -elf | grep python 找到它们,并用 kill -9 [pid] 手动杀死它们。

    您可能正使用其他库生成数据集中的随机数。例如,当通过 fork 启动工作子进程时,NumPy 的 RNG 会被复制。请参阅 torch.utils.data.DataLoader 的文档,了解如何使用其 worker_init_fn 选项正确设置工作进程中的随机种子。

    在具有 DataParalleldata_parallel() 的模块中使用 pack sequence -> recurrent network -> unpack sequence 模式时有一个非常微妙的地方。每个设备上的 forward() 的输入只会是整个输入的一部分。由于默认情况下,解包操作 torch.nn.utils.rnn.pad_packed_sequence() 仅填充到其所见的最长输入,即该特定设备上的最长输入,所以在将结果收集在一起时会发生尺寸的不匹配。因此,您可以利用 的 total_length 参数来确保 forward() 调用返回相同长度

    此外,在批量的维度为dim 1 (第1轴)(即 batch_first = False )时需要额外注意数据的并行性。在这种情况下,pack_padded_sequence 函数的的第一个参数 padding_input 维度将是 [T x B x *] ,并且应该沿dim 1 (第1轴)分散,但第二个参数 input_lengths 的维度为 [B],应该沿dim 0 (第0轴)分散。需要额外的代码来操纵张量的维度。