我已经初始化了两个张量(矩阵):
sm=Var(torch.randn(20,1),requires_grad=True)sm = torch.mm(sm,sm.t()) freq_m=Var(torch.randn(12,20),requires_grad=True)
我从这两个矩阵的数据中创建了两个列表,并使用spearmanr来计算这两个列表之间的相关性值。我创建列表的方式并不重要,但目标是调整矩阵内的值,使计算出的相关性值尽可能接近1。
如果我手动解决这个问题,我会每次调整矩阵中的值0.01(或某个小数),然后重新计算列表和相关性分数。如果新的相关性值高于之前的,我会保存这两个矩阵,并调整不同的值,直到我得到能够提供最高相关性分数的两个矩阵。
PyTorch能够自动完成这个过程吗?我知道PyTorch可以根据方程进行调整,但我希望调整矩阵值的方式不是基于方程,而是基于我计算出的相关性值。任何指导都会非常感激!
回答:
PyTorch有一个自动求导包,这意味着如果你有一个变量,并将其通过可微分函数得到一个标量结果,你可以执行梯度下降来更新变量,以降低或增加标量结果。
所以你需要做的是定义一个在张量级别上工作的函数f,使得f(sm, freq_m)会给你想要的相关性。
然后,你应该做类似以下的事情:
lr = 1e-3for i in range(100): # 100次更新 loss = 1 - f(sm, freq_m) print(loss) loss.backward() with torch.no_grad(): sm -= lr * sm.grad freq_m -= lr * freq_m.grad # 在更新权重后手动将梯度归零 sm.grad.zero_() freq_m.grad.zero_()
学习率基本上是你迈出的步长,学习率过高会导致损失爆炸,学习率过低会导致收敛缓慢,我建议你进行实验。
编辑:回答关于loss.backward
的评论:对于任何可微分函数f,f是多个张量t1, ..., tn
的函数,这些张量具有requires_grad=True
作为结果,你可以计算损失相对于这些张量的梯度。当你执行loss.backward
时,它会计算这些梯度并将它们存储在t1.grad, …, tn.grad中。然后你使用梯度下降更新t1, ..., tn
以便降低f的值。这个更新不需要计算图,这就是为什么你使用with torch.no_grad()
。在循环结束时,你将梯度归零,因为.backward
不会覆盖梯度,而是将新梯度添加到它们上面。更多信息请参见:https://discuss.pytorch.org/t/why-do-we-need-to-set-the-gradients-manually-to-zero-in-pytorch/4903