3

Je programme une expectation-maximization algorithm avec R. Afin d'accélérer le calcul, je voudrais vectoriser ce goulot d'étranglement. Je sais que N est environ cent fois k.Comment accélérer ce type de double boucle?

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]])) 
} 
} 

Il y a aussi cette liste de matrices:

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] 
} 

J'ai accéléré les choses un peu en utilisant:

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) 
} 

et:

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) 
} 

Répondre

4

Pour le premier, je suppose que MyF est une fonction que vous avez créée? Si vous pouvez vous assurer qu'il prendra vos matrices et des listes des entrées et la sortie d'une matrice, vous pouvez faire quelque chose comme:

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

Pour la seconde, je pense que vous faites comme liste, il sera plus difficile à vectoriser. Peut-être qu'au lieu d'une liste de matrices, vous pourriez avoir un tableau en trois dimensions? Alors que MyDf.array [i, j, k] a des dimensions N, d, d (ou d, d, N).

+0

Belle suggestion pour le premier! A propos du second, je pensais que la liste était le seul moyen d'obtenir les tableaux comme dans Matlab. – Wok

+3

Check? Array - il peut gérer plusieurs dimensions. – Wine

+0

Toujours en train d'apprendre. :) – Wok

2

Vous pouvez réduire le travail effectué dans la boucle interne si les choses sont symétriques: A[i,j] = A[j,i]

+0

Merci pour le conseil. Malheureusement, pas de symétrie ici. – Wok

3

Je déteste même suggérer cela prématurément, mais c'est le genre de chose où la construction d'une extension C dans R pourrait avoir du sens. Pour les matrices avec la taille définie (connue) (que vous avez ici!), Les extensions C ne sont pas que dur pour construire, je promets! Le plus méchant ici passerait probablement dans 'myF'

Ma connaissance de R est assez obsolète, mais pour les boucles (particulièrement celle-là!) C'était brutal.

Peut-être que le chronométrage et la détermination de la partie lente seraient utiles? Est-ce myF? Que faire si vous le changez en une identité?

+0

Merci pour le conseil. 'myF' est un appel à la fonction de densité (pdf en abrégé sur Wikipedia) d'une [distribution normale multivariée] (http://en.wikipedia.org/wiki/Multivariate_normal_distribution). C'est un one-liner qui est rapide. C'est vraiment la boucle sur N qui prend le plus de temps. N est 500 alors que k est 4. – Wok

+0

Je suggère également de coller l'ensemble de l'exemple et de le soumettre à la liste-R. Je ne fais plus beaucoup de R, mais E-M est une zone bien comprise! (En particulier avec une simple fonction e-m comme mvnorm!) Je suppose que c'est Résolu (tm). –

+1

Oui, j'essaie juste de le faire moi-même pour faire mes devoirs. :) – Wok