3

Ich programmiere eine expectation-maximization algorithm mit R. Um die Berechnung zu beschleunigen, möchte ich diesen Engpass vektorisieren. Ich weiß, dass N etwa hundert mal k ist.Wie beschleunigt man diese Art von Doppel-For-Schleife?

MyLoglik = 0 
for (i in c(1:N)) 
{ 
for (j in c(1:k)) 
{ 
    MyLoglik = MyLoglik + MyTau[i,j]*log(MyP[j]*MyF(MyD[i,], MyMu[j,], MyS[[j]])) 
} 
} 

Es gibt auch diese Liste von Matrizen:

MyDf.list <- vector("list", k) 
for(i in 1:k) 
{ 
MyDf.list[[i]] <- matrix(0,d,d) 
for (j in c(1:N)) 
{ 
    MyDf.list[[i]] = MyDf.list[[i]] + MyTau[j,i]*as.numeric((MyD[j,]-MyMu[i,])) %*% t(as.numeric(MyD[j,]-MyMu[i,])) 
} 
MyDf.list[[i]] = MyDf.list[[i]]/MyM[i] 
} 

Ich habe mit ein wenig beschleunigt Dinge:

MyLoglik = 0 
for (j in c(1:k)) 
{ 
MyR= apply(MyD, 1, function(x) log(MyP[j]*MyF(x, MyMu[j,], MyS[[j]]))) 
MyLoglik = MyLoglik + sum(MyTau[,j]*MyR) 
} 

und:

d = dim(MyD)[2] 
MyDf.list <- vector("list", k) 
for(i in 1:k) 
{ 
MyDf.list[[i]] <- matrix(0,d,d) 
MyR= apply(MyD, 1, function(x) as.numeric((x-MyMu[i,])) %*% t(as.numeric(x-MyMu[i,]))) 
MyDf.list[[i]] = matrix(rowSums(t(MyTau[,i]*t(MyR)))/MyM[i],d,d) 
} 

Antwort

4

Für die erste nehme ich an, MyF ist eine Funktion, die Sie gemacht haben? Wenn Sie sicherstellen können sie Ihre Matrizen und Listen als Ein- und Ausgang eine Matrix nehmen, Sie so etwas wie tun könnte:

MyLoglik = sum(MyTau%*%log(MyP)) + sum(MyTau*log(MyF(MyD, MyMu, MyS))) 

Für die zweite, denke ich, weil Sie es als Liste tun wird es sein, schwieriger zu vektorisieren. Vielleicht könnte man anstelle einer Liste von Matrizen ein 3-dimensionales Array haben? Also hat MyDf.array [i, j, k] Dimensionen N, d, d (oder d, d, N).

+0

Netter Vorschlag für den ersten! Über die zweite, dachte ich, war die einzige Möglichkeit, die Arrays wie in Matlab zu bekommen. – Wok

+3

Überprüfen Sie? Array - es kann mehrere Dimensionen behandeln. – Wine

+0

Immer lernen. :) – Wok

2

Sie können sich auf der Arbeit in der inneren Schleife fertig geschnitten, wenn die Dinge symmetrisch sind: A[i,j] = A[j,i]

+0

Danke für den Rat. Leider keine Symmetrie hier. – Wok

3

Ich hasse es zu früh zu schlagen sogar vor, aber das ist die Art von Dingen, wo in R einen C-Erweiterungsbau könnte Sinn machen. Für Matrizen mit definierter (bekannter) Größe (die du hier hast!), Sind C-Erweiterungen nicht das hart bauen, das verspreche ich dir! Das bösartigste Bit hier wäre wahrscheinlich in "myF"

übergeben. Mein R-Wissen ist ziemlich veraltet, aber für Schleifen (besonders wie diese!) War früher brutal.

Vielleicht Timing und herauszufinden, welcher Teil langsam ist, würde helfen? Ist es myF? Was, wenn du es zu einer Identität änderst?

+0

Danke für den Hinweis. 'myF' ist ein Aufruf zur Dichtefunktion (bei Wikipedia als pdf abgekürzt) einer [multivariaten Normalverteilung] (http://en.wikipedia.org/wiki/Multivariate_normal_distribution). Dies ist ein One-Liner, der schnell ist. Dies ist wirklich die Schleife über N, die die meiste Zeit benötigt. N ist 500, während k 4. ist. – Wok

+0

Ich würde auch vorschlagen, Pastebinning das ganze Beispiel und an die R-Liste zu übermitteln. Ich mache nicht mehr viel R, aber E-M ist ein gut verstandener Bereich! (insb. mit einer einfachen E-m-Funktion wie mvnorm!) Ich vermute, das ist Solved (tm). –

+1

Ja, ich versuche es nur für die Hausaufgaben. :) – Wok