给定一个训练好的模型(M),我感兴趣的是计算池中新的(看不见的)例子的效用(对于一个主动学习任务)。为此,我需要计算在每个新样本上训练M时梯度的大小。在代码中,它类似于:
losses, grads = [], []
for i in range(X_pool.shape[0]):
pred = model(X_pool[i:i+1])
loss = loss_func(pred, y_pool[i:i+1])
model.zero_grad()
loss.backward()
losses.append(loss)
grads.append(layer.weight.grad.norm())
然而,当有大量的示例时,这是相当慢的,特别是因为这将是我的场景中的内部循环。在pytorch中有没有更有效的方法来做到这一点?
2条答案
按热度按时间tyu7yeag1#
根据代码,看起来你只看到了模型中一层的渐变。您可以将此层拆分为多个副本,每个副本仅采用批处理的一个组件。这样,仅针对该特定样本计算梯度,但在其他任何地方使用批处理。
这里有一个完整的例子,比较你的方法(方法1)和我提出的方法(方法2)。这应该很容易扩展到更复杂的网络。
两种算法之间的数值差异只是浮点误差。
我还没有在更大的网络中进行过测试,但我使用了
batch_size
并在网络中运行了多个批处理,在这个简单的模型中看到了2- 3倍的加速。在一个更复杂的模型中,它应该更重要,因为除了被复制的层之外,您可以在所有层上获得批处理的性能优势。警告这可能不适用于
DataParallel
。3pvhb19x2#
你可以使用torch.func.vmap来实现。它是版本2中的一个新实用程序,它通过在函数上引入批处理维度来向量化函数。在你的例子中,你可以编写一个纯函数来计算单个例子的梯度,然后使用vmap将其向量化为一批例子:
我写的代码灵感来自Pytorch教程here。这是一个矢量化的代码,因此预计它的工作速度比手动迭代每个训练示例要快得多。