我正在使用Pytorch为CIFAR10做一些分类任务,对于每一次迭代,我必须对每一批进行一些预处理,然后才能前馈到模型中。以下是每个批次上预处理部分的代码:
S = torch.zeros((batch_size, C, H, W))
for i in range(batch_size):
img = batch[i, :, :, :]
for c in range(C):
U, _, V = torch.svd(img[c])
S[i, c] = U[:, 0].view(-1, 1).matmul(V[:, 0].view(1, -1))
但是,这个计算非常慢。有没有什么方法可以加速这段代码?
发布于 2020-02-09 15:37:06
批处理计算
假设您有PyTorch >= 1.2.0,那么支持批处理奇异值分解,因此您可以使用
U, _, V = torch.svd(batch)
S = U[:, :, :, 0].unsqueeze(3) @ V[:, :, :, 0].unsqueeze(2)
我发现它的平均速度比迭代版本快一点。
截断奇异值分解(仅处理器)
如果你没有cuda加速,你可以使用截断的SVD来避免计算不必要的奇异值/向量。不幸的是,PyTorch不支持截断奇异值分解和AFAIK,没有可用的批处理或图形处理器版本。我知道有两种选择
这两个选项都允许您选择要返回的组件数量。在OP的原始问题中,我们只需要第一个组件。
尽管我没有在稀疏矩阵上使用它,但我发现使用k=1
的svds
在CPU张量上比torch.svd
快大约10倍。我发现randomized_svd
只快了大约2倍。您的结果将取决于实际数据。此外,svds
应该比randomized_svd
更精确一些。请记住,这些结果与torch.svd
结果之间会有很小的差异,但它们应该可以忽略不计。
import scipy.sparse.linalg as sp
import numpy as np
S = torch.zeros((batch_size, C, H, W))
for i in range(batch_size):
img = batch[i, :, :, :]
for c in range(C):
u, _, v = sp.svds(img[c], k=1)
S[i, c] = torch.from_numpy(np.outer(u, v))
发布于 2021-03-26 20:31:48
PyTorch现在拥有类似于numpy的linalg
模块的speed optimised Linear Algebra operations,包括torch.linalg.svd
奇异值分解的实现使用LAPACK例程?gesdd (一种分而治之的算法)而不是?gesvd来提高速度。类似地,GPU上的奇异值分解使用CUDA10.1.243和更高版本上的cuSOLVER例程gesvdj和gesvdjBatched,并在早期版本的CUDA上使用MAGMA例程gesdd。
发布于 2022-02-11 08:48:48
您可以在Github!https://github.com/KinglittleQ/torch-batch-svd上查看此批处理的奇异值分解
https://stackoverflow.com/questions/60133809
复制相似问题