我是Pytorch的新手,在torch.cat遇到问题。
在我的场景中,我有一个训练有素的模型,该模型基本上是矢量矩阵,我想执行以下操作:
这是我的计算和问题的最小示例:
import torch
from torch import optim
from torch.nn.parameter import Parameter
# the old, already-trained vectors (2 vecs with 5 elements each)
old_vecs = torch.rand(2, 5)
# the new vector to train (1 vec with 5 elements).
# This has to be a Parameter, so it can be passed to an Optimizer to have it trained
new_vec = Parameter(torch.rand(1, 5))
# concatenate old_vecs and new_vec
all_vecs = torch.cat((old_vecs, new_vec), 0)
# create the Optimizer with the new_vec to train
optimizer = optim.SGD([new_vec], lr=1e-1)
for epoch in range(5):
loss = all_vecs.sum()
loss.backward()
optimizer.step()
optimizer.zero_grad()
通过打印训练前后的向量值,我获得了以下读数:
new_vec before training:
Parameter containing: tensor([[0.4151, 0.6478, 0.5142, 0.2373, 0.5643]], requires_grad=True)
new_vec after training:
Parameter containing: tensor([[-0.0849, 0.1478, 0.0142, -0.2627, 0.0643]], requires_grad=True)
all_vecs[2] after training:
tensor([0.4151, 0.6478, 0.5142, 0.2373, 0.5643], grad_fn=<SelectBackward>)
很明显,new_vec已更新,但all_vecs [2]未更新。 显然,当运行torch.cat时,将生成新的张量all_vecs 具有独立的内容。所以vec_new和all_vecs [2]具有独立的值,并且由于我唯一的参数是new_vec,因此all_vecs [2]就像旧的冻结矢量一样。
这是问题,因为我的损失是根据all_vecs计算的,而不是根据new_vec计算的。 由于all_vecs无法更改,因此损耗及其梯度将永远不会减少(当然,这将影响new_vec的训练方式)。
我可以通过在每次迭代时手动更新all_vecs [2]的值来轻松解决问题:
for epoch in range(5):
with torch.no_grad():
all_vecs[2] = new_vec
loss = all_vecs.sum()
loss.backward()
optimizer.step()
optimizer.zero_grad()
但是说实话,这感觉像是一个bad头,我需要使我的代码尽可能“干净”。 有什么建议?除了不为张量值分配新内存之外,torch.cat还有其他替代方法吗?