Ho quattro tensori multidimensionali v[i,j,k]
, a[i,s,l]
, w[j,s,t,m]
, x[k,t,n]
in Numpy, e sto cercando di calcolare il tensore z[l,m,n]
data da:riduzione efficiente dei molteplici tensori in Python
z[l,m,n] = sum_{i,j,k,s,t} v[i,j,k] * a[i,s,l] * w[j,s,t,m] * x[k,t,n]
Tutti i tensori sono relativamente piccolo (diciamo meno di 32k elementi in totale), tuttavia ho bisogno di eseguire questo calcolo molte volte, quindi vorrei che la funzione avesse il minor overhead possibile.
ho cercato di attuarlo utilizzando numpy.einsum
in questo modo:
z = np.einsum('ijk,isl,jstm,ktn', v, a, w, x)
ma era molto lento. Ho provato anche la seguente sequenza di chiamate numpy.tensordot
:
z = np.zeros((a.shape[-1],w.shape[-1],x.shape[-1]))
for s in range(a.shape[1]):
for t in range(x.shape[1]):
res = np.tensordot(v, a[:,s,:], (0,0))
res = np.tensordot(res, w[:,s,t,:], (0,0))
z += np.tensordot(res, x[:,s,:], (0,0))
all'interno di un doppio ciclo for per sommare s
e t
(sia s
e t
sono molto piccole, così che non è troppo di un problema). Questo ha funzionato molto meglio, ma non è ancora veloce come non vorrei. Penso che questo potrebbe essere dovuto a tutte le operazioni che tensordot
deve eseguire internamente prima di prendere il prodotto reale (ad esempio, permutare gli assi).
Mi chiedevo se esiste un modo più efficiente per implementare questo tipo di operazioni in Numpy. Inoltre non mi dispiacerebbe implementare questa parte in Cython, ma non sono sicuro di quale sarebbe l'algoritmo giusto da usare.
Potresti condividere le implementazioni di 'numpy.einsum' e' numpy.tensordot'? – Divakar
@Divakar: sicuro. L'implementazione di 'einsum' è semplicemente' z = np.einsum ('ijk, isl, jstm, ktn', v, a, w, x) '. L'implementazione 'tensordot' è ' res = np.tensordot (v, a, (0,0)) res = np.tensordot (res, w, (0,0)) res = np.tensordot (res , x, (0,0)) ' – Alessandro
Si prega di aggiungere tali implementazioni alla domanda utilizzando il pulsante" modifica "sotto la domanda. – Divakar