Как я могу избежать цикла, если мне нужно выполнить умножение матрицы?

#python #performance #matrix #pytorch

Вопрос:

У меня есть следующий код:

 import numpy as np
import torch

y = torch.ones((1000,10)) #This is the output of a neural network which does not matter here
theta_min = 0; theta_max = np.pi; K = 10; sigma = 10;
z = torch.zeros(y.shape)
for i in range(0,y.shape[0]):
    theta = np.random.uniform(theta_min, theta_max)
    vector = np.reshape(np.exp(-1j * np.arange(0,K) * np.pi * np.sin(theta)),(-1,1))
    vector = torch.tensor(vector)
    alpha = sigma * np.random.randn()
    z[i,:] = alpha * vector @ vector.T @ y[i,:].T
 

Как я могу избежать цикла, чтобы сделать код быстрее?

Комментарии:

1. Можете ли вы привести воспроизводимый пример? Вероятно, вам просто нужно скопировать вектор в матрицу и заставить альфа нарисовать матрицу.

2. Да, я тоже перешел y на матрицу. Это был не вектор, это была ошибка

Ответ №1:

Я верю, что это сработает:

 import numpy as np
import torch

y = torch.ones((1000,10))
theta_min = 0; theta_max = np.pi; K = 10; sigma = 10;
z = torch.zeros(y.shape)

theta = np.random.uniform(theta_min, theta_max, y.shape)
vector = np.exp(-1j * np.arange(0,K) * np.pi * np.sin(theta))
vector = torch.FloatTensor(vector)

temp = (vector.T @ vector)
alpha = sigma * torch.rand(temp.shape)
z = (alpha*temp @ y.T).T
 

чтобы ускорить его еще больше, вы можете использовать горелку для всего процесса:

 import numpy as np
import torch

y = torch.ones((1000,10)).float()
theta_min = 0; theta_max = np.pi; K = 10; sigma = 10;
alpha = sigma * torch.rand(1)

theta = torch.rand(y.shape)*(np.pi)
vector = torch.exp(-1j * torch.arange(0,K) * np.pi * torch.sin(theta)).float()

temp = (vector.T @ vector)
alpha = sigma * torch.rand(temp.shape)
z = (alpha*temp @ y.T).T
 

Комментарии:

1. Но проблема в том, что в моем коде для каждого случайного значения тета у меня есть вектор, поэтому 1 тета умножается на 0,1,2,…,K-1. Однако в вашем коде 1 тета умножается на 1, другая тета-на 2 и так далее. Я бы хотел, чтобы только 1 случайное значение тета определяло массив vector

Ответ №2:

Следуя решению Меган Харди, я попытался вместо использования 3d-массивов. Мы сделаем несколько бесполезных операций, но это лучше, чем цикл for. Код будет выглядеть следующим образом:

 y = torch.ones((1000,10)).type(torch.complex64) 
theta_min = 0; theta_max = np.pi; K = 10; sigma = 10;

theta = torch.rand(y.shape[0],1,1) * np.pi  #Each slice in the 0 dimension will be treated separately
temp = torch.reshape(torch.arange(0,K),(-1,1))    #Necessary so that it doesn't have dimensions (10,), but (10,1)
vector = torch.exp(-1j * temp * np.pi * torch.sin(theta))
matrix = vector @ torch.transpose(vector,1,2)   #Maintain the 0 dimension but exchange dimension 1 and 2

alpha = sigma * torch.rand(1)

z = alpha * matrix @ y.T    #This makes more operations that necessary
temp = range(0,y.shape[0])  
z = alpha * z[temp,:,temp]  #Take only the desired columns