2017-01-14 5 views
4

У меня есть трехмерный тензор A размера (M, N, N). У меня также есть весовой вектор р длина М. Я хочу, чтобы вычислитьСамый быстрый способ взять

enter image description here

Размера N может быть большим, так что я хочу осуществить его в эффективном способе. Я использую следующий код:

import numpy as np 
temp=np.array([p[m]*A[m] for m in range(M)]) 
B=sum(temp); 

Я хочу знать, существуют ли более быстрые и эффективные способы реализации этого. Причина, по которой это важно, состоит в том, что, когда N велико, вышеупомянутая переменная temp сохраняет M этих N * N-матриц. Поэтому я думаю, что мы можем использовать «цикл цикла», возможно, но я читал, что для циклов медленнее, чем списки.

ответ

2

По крайней мере, из тензоров Я тестировал его, этот фрагмент до 3 раз быстрее:

sum(np.einsum('ij...,i->ij...', A, p)) 

Вот сравнение для различных методов, которые были разделены:

base  = sum(np.array([p[m]*A[m] for m in range(M)])) 
einsum1 = sum(np.einsum('ij...,i->ij...', A, p)) 
einsum2 = np.einsum('ijk,i->jk', A, p) 
einsum3 = np.einsum('ij...,i->j...', A, p) 
dot  = p.dot(A.reshape(A.shape[0],-1)).reshape(A.shape[1],-1) 
tensordot = np.tensordot(p, A, (0, 0)) 

для M = 1000, N = 100 (по сравнению с базой):

einsum1 = 1.11x 
einsum2 = 5.83x 
einsum3 = 6.26x 
dot  = 8.60x 
tensordot = 9.83x 
+0

Как насчет np.tensordot (p, A, (0,0))? – pikachuchameleon

+0

«tensordot» один значительно быстрее, чем тензор (в 10 раз быстрее, когда M = 1000, N = 100) –

+0

Вы имеете в виду быстрее, чем вышеупомянутый метод einsum? – pikachuchameleon

0
In [24]: A=np.arange(3*2*2).reshape(3,2,2)  
In [25]: p=np.array([1,2,3]) 

In [26]: temp=np.array([p[m]*A[m] for m in range(len(p))]) 
In [27]: sum(temp) # python sum 
Out[27]: 
array([[32, 38], 
     [44, 50]]) 

In [28]: np.einsum('i...,i->...',A,p) 
Out[28]: 
array([[32, 38], 
     [44, 50]]) 

ijk,i->jk также работает.

Хотя не обязательно быстрый, temp может быть рассчитан с помощью простого вещания. np.sum(..., axis=0) является эквивалентом Python sum().

In [30]: (A*p[:,None,None]).sum(axis=0) 
Out[30]: 
array([[32, 38], 
     [44, 50]])