问题描述
在我的损失函数的某个地方,我反转了一个大小为 64*64 的复杂矩阵。尽管 torch.tensor 支持复矩阵求逆,但由于出现此错误,因此无法在训练循环中计算梯度:
RuntimeError: inverse 不支持复杂类型输出的自动微分。
有没有人有解决这个问题的方法?一个自定义函数而不是 torch.inverse 也许?
解决方法
您可以使用复矩阵的实值分量自己进行逆运算。
先了解一些线性代数:
一个复矩阵 C
可以写成两个 real 矩阵 A
和 B
的和(j
是 - 1):
C = A + jB
找到C
的逆基本上是找到两个实值矩阵x
和y
,使得
(A + jB)(x + jy) = I + j0
既然我们知道如何将复数矩阵求逆简化为实值矩阵求逆,我们就可以使用 pytorch 的 solve
为我们进行求逆。
def complex_inverse(C):
A = torch.real(C)
B = torch.imag(C)
# construct the left hand side of the system of equations
# side note: from pytorch 1.7.1 you can use vstack and hstack instead of cat
lhs = torch.cat([torch.cat([A,-B],dim=1),torch.cat([B,A],dim=1)],dim=0)
# construct the rhs of the system of equations
rhs = torch.cat([torch.eye(A.shape[0]).to(A),torch.zeros_like(A)],dim=0)
# solve the system of equations
raw,_ = torch.solve(rhs,lhs)
# write the solution as a single complex matrix
iC = raw[:C.shape[0],:] + 1j * raw[C.shape[0]:,:]
return iC
您可以使用 numpy 验证解决方案:
# C is a complex torch tensor
iC = complex_inverse(C)
with torch.no_grad():
print(np.isclose(iC.cpu().numpy() @ C.cpu().numpy(),np.eye(C.shape[0])).all())
请注意,通过使用块矩阵的逆技巧,您可以降低 solve
操作的计算成本。
从 1.9 开始,PyTorch 现在支持复杂的 autograd。