Пакетное вычисление
Если у вас есть PyTorch> = 1.2.0, то поддерживается пакетный SVD, так что вы можете использовать
U, _, V = torch.svd(batch)
S = U[:, :, :, 0].unsqueeze(3) @ V[:, :, :, 0].unsqueeze(2)
, который я нашел немного быстрее в среднем, чем итеративная версия.
Усеченный SVD (только ЦП)
Если у вас нет ускорения cuda, вы можете использовать усеченный SVD для Избегайте вычисления ненужных особых значений / векторов. К сожалению, PyTorch не поддерживает усеченный SVD и AFAIK. Пакетная или графическая версия недоступна. Мне известны два варианта:
Оба из них позволяют вам выбрать количество компонентов для возврата. В исходном вопросе OP нам нужен только первый компонент.
Несмотря на то, что я не использую его на разреженных матрицах, я обнаружил, что svds
с k=1
примерно в 10 раз быстрее, чем torch.svd
на тензорах процессора. Я обнаружил, что 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))