唯物是真 @Scaled_Wurm

プログラミング(主にPython2.7)とか機械学習とか

RでPLSA(PLSI)

Probabilistic Latent Semantic AnalysisとProbabilistic Latent Semantic Indexingのどっちの名前を使えばいいのかわかりませんが,昔PLSAの実装に挑戦したときのソースが出てきたので晒しとく.
ちゃんと動いてるかどうかは不明.Tempered EMアルゴリズムではなくて普通のEMアルゴリズム
Rのforループは遅いので,行列演算とapplyを駆使してどれだけforループを減らせるかという目的で書いてたらソースコードがカオスになって諦めた.
行列演算とapplyに頭を使うぐらいなら別の言語でforループで書いたほうが…….

#data
x <- matrix(c(1,1,1,0,0,0, 1,0,1,0,0,0, 1,1,0,0,0,0,0, 0,0,1,1,1,0, 0,0,1,0,1,0,0,0,1,1,0), 6)

#Topic Num
Z<-2
#Max iteration
MI<-50

#initialize
	D <- dim(x)[1]
	W <- dim(x)[2]

#parameters
	pz_dw <- array(0, dim=c(Z, D, W))
	pd_z <- matrix(runif(Z*D), D, Z)
	pw_z <- matrix(runif(Z*W), W, Z)
	pd_z <- t(t(pd_z) / apply(pd_z, 2, sum))
	pw_z <- t(t(pw_z) / apply(pw_z, 2, sum))
	pz <- matrix(1 / Z, Z)

################################

	Q1 <- function() {
		sum <- 0
		for(d in 1:D){
			for(w in 1:W){
				sum <- sum + x[d, w] * sum(pz * pw_z[w, ] * pd_z[d, ])
			}
		}
		sum
	}

	q1 <- Q1()

	for(t in 1:MI){
		cat("Iteration : ", t, ", Q1 : ", q1,  "\n")
#E-step 
		for(d in 1:D){
			for(w in 1:W){
				pz_dw[, d, w] <- pz * pw_z[w,] * pd_z[d, ] / sum(pz * pw_z[w,] * pd_z[d, ])
			}
		}
#M-step
		for(z in 1:Z){
			pw_z[, z] <- apply(x * pz_dw[z, , ], 2, sum) / sum(x * pz_dw[z,,])
		}
		pw_z <- t(t(pw_z) / apply(pw_z, 2, sum))
		
		for(d in 1:D){
			pd_z[d, ] <- apply(as.numeric(x[d, ]) * t(pz_dw[, d, ]), 2, sum) / sum(x * pz_dw[z,,])
		}
		pd_z <- t(t(pd_z) / apply(pd_z, 2, sum))
		
		s <- sum(x)
		for(z in 1:Z){
			pz[z] <- sum(x * pz_dw[z, , ]) / s
		}
		pz <- pz / sum(pz)

		qt1 <- Q1()
		if(abs(q1 - qt1) <= 1e-10) {
			break;
		} else {
			q1 <- qt1
		}

	}
#output
pd_z