ускорить СВД в пыторье - PullRequest
       70

ускорить СВД в пыторье

1 голос
/ 09 февраля 2020

Я выполняю некоторую классификационную задачу для CIFAR10 с Pytorch, и для каждой итерации мне нужно выполнить некоторую предварительную обработку для каждого пакета, прежде чем я смогу перейти к модели. Ниже приведен код для предварительной обработки каждой партии:

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))

Однако этот расчет очень медленный. Есть ли способ ускорить этот код?

1 Ответ

0 голосов
/ 09 февраля 2020

Пакетное вычисление

Если у вас есть 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))

...