Diese Frage konzentriert sich auf numpy.effizient parafac/CP Produkt in numpy
Ich habe eine Reihe von Matrizen, die alle die gleiche Anzahl von Spalten teilen und unterschiedliche Anzahl von Zeilen haben. Nennen wir sie A, B, C, D usw. und lassen ihre Dimensionen IaxK IbxK, IcxK, usw. sein. ib, ic, id, dh, ...) = \ sum_k A (ia, k) B (ib, k) C (ic, k) ...
Also wenn ich zwei Faktoren habe, lande ich mit einfachem Matrixprodukt.
Natürlich habe ich diese „von Hand“ durch äußere Produkte berechnen kann, so etwas wie:
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
Dennoch würde ich etwas viel rechentechnisch effizienter mögen, wie unter Berufung numpy Funktionen auf gebautet, aber ich kann nicht finden Relevante Funktionen, kann mir jemand helfen?
Cheers, dank
Es ist in der Tat mächtig Voodoo, und läuft sogar etwa doppelt so schnell wie das, was ich produziert – Jaime
Nizza. Hast du die Geschwindigkeit dieser Version mit deinem Original verglichen? Ich habe versucht, beide mit vier Arrays mit Formen (10,3), (24,3), (15,3) und (75,3) zu verwenden. Ihre Originalversion benötigt ca. 2ms, und die Version mit'Einsum' benötigt ca. 7,5ms. –
Es sieht so aus, als würde einsum von Multicore-Architekturen profitieren, während meine ursprünglichen Sachen dies nicht taten. Außerdem habe ich experimentell festgestellt, dass es besser skaliert wurde (wahre Fälle von Interesse sind eher für Matrizen von einigen tausend Zeilen und etwa 50 Spalten). Ich werde das ausprobieren – antoine