Questa domanda si concentra su numpy.calcolo efficiente del prodotto parafac/CP in numpy
Ho un set di matrici che condividono tutti lo stesso numero di colonne e hanno un numero diverso di righe. Chiamiamoli A, B, C, D, ecc e lascia che le loro dimensioni siano IaxK IbxK, IcxK, ecc
Quello che voglio è calcolare in modo efficiente il tensore IaxIbxIc ... definito come segue: P (ia, ib, ic, id, ie, ...) = \ sum_k A (ia, k) B (ib, k) C (ic, k) ...
Quindi se ho due fattori, finisco con un prodotto a matrice semplice.
Certo che posso calcolare questo "a mano" attraverso prodotti esterni, qualcosa di simile:
def parafac(factors,components=None):
ndims = len(factors)
ncomponents = factors[0].shape[1]
total_result=array([])
if components is None:
components=range(ncomponents)
for k in components:
#for each component (to save memory)
result = array([])
for dim in range(ndims-1,-1,-1):
#Augments model with next dimension
current_dim_slice=[slice(None,None,None)]
current_dim_slice.extend([None]*(ndims-dim-1))
current_dim_slice.append(k)
if result.size:
result = factors[dim].__getitem__(tuple(current_dim_slice))*result[None,...]
else:
result = factors[dim].__getitem__(tuple(current_dim_slice))
if total_result.size:
total_result+=result
else:
total_result=result
return total_result
Eppure, vorrei qualcosa di molto più computazionalmente efficiente, come basandosi su builtin funzioni NumPy, ma non riesco a trovare funzioni rilevanti, qualcuno può aiutarmi?
Saluti, grazie
È davvero potente voodoo, e anche corre circa il doppio della velocità di quello che ho prodotto – Jaime
Nice. Hai confrontato la velocità di questa versione con quella originale? Ho provato entrambi utilizzando quattro array con forme (10,3), (24,3), (15,3) e (75,3). La tua versione originale impiega circa 2ms, e la versione che usa 'einsum' richiede circa 7.5ms. –
Sembra che einsum possa beneficiare di architetture multicore mentre le mie cose originali no. Inoltre, ho notato sperimentalmente che ha avuto una maggiore scalabilità (i veri casi di interesse sono piuttosto per matrici di alcune migliaia di righe e qualcosa come 50 colonne). Proverò questo – antoine