【问题标题】:Is there a way to compute the matrix logarithm of a Pytorch tensor?有没有办法计算 Pytorch 张量的矩阵对数?
【发布时间】:2023-02-18 16:08:00
【问题描述】:

我正在尝试在 Pytorch 中计算矩阵对数,但我需要保留张量,因为我随后应用了梯度,这意味着我不能使用 numpy 数组。 基本上,我正在尝试做与https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.logm.html 相同的事情,但使用的是 Pytorch 张量。 谢谢。

【问题讨论】:

  • 你试过在一些torch.tensor上申请scipy.linalg.logm吗?从我的实验来看,有一些与此相关的错误,但它只是订单10^-5
  • @Hadar OP 要求与 pytorch autograd 引擎兼容的版本——不幸的是,这不适用于 scipy 实现。

标签: pytorch


【解决方案1】:

不幸的是矩阵对数(不像matrix exponential)是not implemented yet,但是matrix powers是,这意味着 同时,您可以使用 power series expansion 来近似矩阵对数,并在获得足够的精度后截断它。

或者,Lezcano 通过伴随 here 提出了可微分矩阵对数的(慢)解。我会引用他们建议的解决方案:

import scipy.linalg
import torch

def adjoint(A, E, f):
    A_H = A.T.conj().to(E.dtype)
    n = A.size(0)
    M = torch.zeros(2*n, 2*n, dtype=E.dtype, device=E.device)
    M[:n, :n] = A_H
    M[n:, n:] = A_H
    M[:n, n:] = E
    return f(M)[:n, n:].to(A.dtype)

def logm_scipy(A):
    return torch.from_numpy(scipy.linalg.logm(A.cpu(), disp=False)[0]).to(A.device)

class Logm(torch.autograd.Function):
    @staticmethod
    def forward(ctx, A):
        assert A.ndim == 2 and A.size(0) == A.size(1)  # Square matrix
        assert A.dtype in (torch.float32, torch.float64, torch.complex64, torch.complex128)
        ctx.save_for_backward(A)
        return logm_scipy(A)

    @staticmethod
    def backward(ctx, G):
        A, = ctx.saved_tensors
        return adjoint(A, G, logm_scipy)

logm = Logm.apply

【讨论】:

  • 非常有趣,谢谢!
【解决方案2】:

在Pytorch中很容易实现如下:

进口手电筒

a=手电筒.randn(5,10)

cov=torch.cov(a)

u, s, v = torch.linalg.svd(cov)

log_cov=torch.matmul(torch.matmul(u, torch.diag_embed(torch.log(s))), v)

您可以轻松验证 log_cov 和 log_cov_np 是否相同。

log_cov_np=scipy.linalg.logm(cov.detach().numpy())

如果 cov 是奇异的,则可以使用正则化方法使其具有用于计算矩阵对数的良好条件数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    • 1970-01-01
    • 2016-11-09
    • 2016-09-29
    • 2014-09-07
    • 1970-01-01
    相关资源
    最近更新 更多