Python 在PyTorch中加速SVD

Python 在PyTorch中加速SVD,python,pytorch,batch-processing,matrix-multiplication,svd,Python,Pytorch,Batch Processing,Matrix Multiplication,Svd,我正在用Pytorch为CIFAR10做一些分类任务,对于每个迭代,我必须对每个批次进行一些预处理,然后才能反馈到模型。 以下是每批预处理部件的代码: S=焊炬零点((批次尺寸,C,H,W)) 对于范围内的i(批次大小): img=批次[i,:,:,:] 对于范围(c)内的c: U、 _uv=torch.svd(img[c]) S[i,c]=U[:,0]。视图(-1,1)。matmul(V[:,0]。视图(1,-1)) 然而,这种计算非常缓慢。有什么方法可以加快这段代码的速度吗?批量计算 假设

我正在用Pytorch为CIFAR10做一些分类任务,对于每个迭代,我必须对每个批次进行一些预处理,然后才能反馈到模型。 以下是每批预处理部件的代码:

S=焊炬零点((批次尺寸,C,H,W))
对于范围内的i(批次大小):
img=批次[i,:,:,:]
对于范围(c)内的c:
U、 _uv=torch.svd(img[c])
S[i,c]=U[:,0]。视图(-1,1)。matmul(V[:,0]。视图(1,-1))

然而,这种计算非常缓慢。有什么方法可以加快这段代码的速度吗?

批量计算

假设PyTorch>=1.2.0,则支持批处理SVD,因此可以使用

U, _, V = torch.svd(batch)
S = U[:, :, :, 0].unsqueeze(3) @ V[:, :, :, 0].unsqueeze(2)
我发现它平均比迭代版本快一点


截断SVD(仅限CPU)

如果没有cuda加速,可以使用截断SVD来避免计算不必要的奇异值/向量。不幸的是,Pytork不支持截断的SVD和AFAIK,没有批处理或GPU版本可用。我知道有两种选择

这两个选项都允许您选择要返回的组件数量。在OP的原始问题中,我们只需要第一个组件

即使我没有在稀疏矩阵上使用它,我发现
svd
k=1
比CPU张量上的
torch.svd
快10倍左右。我发现随机化的svd只快了2倍左右。您的结果将取决于实际数据。另外,
svd
应该比
随机化\u svd
更精确一些。请记住,这些结果与
torch.svd
结果之间存在微小差异,但它们应该可以忽略不计

将scipy.sparse.linalg导入为sp
将numpy作为np导入
S=焊炬零点((批次尺寸,C,H,W))
对于范围内的i(批次大小):
img=批次[i,:,:,:]
对于范围(c)内的c:
u、 _uv=sp.svds(img[c],k=1)
S[i,c]=火炬从_numpy(np.外部(u,v))
PyTorch现在有类似于numpy的
linalg
模块,包括
torch.linalg.svd

SVD在CPU上的实现使用LAPACK例程gesdd(一种分治算法)代替gesvd来提高速度。类似地,GPU上的SVD使用CUDA 10.1.243及更高版本上的cuSOLVER例程gesvdj和Gesvdjbatch,并在CUDA的早期版本上使用MAGMA例程gesdd


我修正了密码。那么有没有办法加速这个版本呢?你可以尝试使用numpy的SVD,然后使用来加速它。Numba没有为SVD计算提供任何加速。我以前尝试过这个,但没有任何改进,因为torch.SVD()可能在GPU上。我想知道这两个for循环是否可以转换为批处理计算。