EM算法
leengsmile
2016年9月24日
EM 算法
本文檔介紹如何在R
語言中,通過EM算法别威,估計高斯混合模型的參數(shù)。首先通過簡單的例子,用簡單的程序描述EM算法估計高斯混合模型參數(shù)的過程吁讨,再介紹如何使用第三方包實(shí)現(xiàn)相應(yīng)的估計。
為保證數(shù)據(jù)結(jié)果的可重復(fù)性峦朗,設(shè)置隨機(jī)數(shù)種子
set.seed(123)
首先需要高斯混合模型的數(shù)據(jù)
n <- 1000
mean_s <- c(1, 7)
y <- sample(c("head", "tail"), size = n, replace = TRUE, prob = c(0.25, 0.75))
x <- rnorm(n = 1000, mean = mean_s[1])
tails <- y %in% c("tail")
x[tails] <- rnorm(sum(tails), mean = mean_s[2])
上述產(chǎn)生的混合模型是均值分別為1和7建丧,標(biāo)準(zhǔn)差均為1的混合模型,且混合的概率為(0.25, 0.75)
波势。 也就是說翎朱,混合模型中的觀測值有0.25的概率來自于均值為1的高斯分布,有0.75的概率來自于均值為7的高斯分布尺铣。
其概率概率密度函數(shù)為
require(lattice)
densityplot(~x, par.settings = list(plot.symbol = list(col = factor(y))))
數(shù)據(jù)分布明顯拴曲,呈現(xiàn)很好的可分性。下面需要估計對應(yīng)的正太分布的均值凛忿,以及混合概率澈灼。這里假定方差恒定且相等,均為1店溢。
probs <- c(0.5, 0.5)
mu_s <- c(0, 1)
sigma_s <- c(1, 1)
for(i in seq(10))
{
ps <- matrix(0, ncol = 2, nrow = n)
for(j in seq(2))
{
ps[, j] <- probs[j] * dnorm(x, mean = mu_s[j], sd = sqrt(sigma_s[j]))
}
ps <- ps / rowSums(ps)
for(j in seq(2))
{
sigma_s[j] <- sum( ps[, j] * (x - mu_s[j])^2) / sum(ps[, j])
mu_s[j] <- sum(x * ps[, j]) / sum(ps[, j])
probs[j] <- mean(ps[, j])
}
}
cat(
"mean:", mean_s, "\n",
"sigma:", sqrt(sigma_s), "\n",
"prob:", probs, "\n",
sep = " "
)
## mean: 1 7
## sigma: 0.9415133 0.9913065
## prob: 0.2469451 0.7530549
估計的均值分別為0.9748991, 6.9999522叁熔,混合概率為0.2469451, 0.7530549。經(jīng)過10次迭代床牧,估計值已經(jīng)很接近精確值荣回。
可以將上述求解的過程封裝成一個函數(shù)
gmm <- function(x, mean, sd = NULL)
{
num <- length(mean)
if(is.null(sd))
{
sd <- rep(1, num)
}
epsilon <- 1e-4
probs <- rep(1/num, num)
mu_s <- mean
sigma_s <- sd ^ 2
n <- length(x)
while(TRUE)
{
ps <- matrix(0, ncol = num, nrow = n)
for(j in seq(num))
{
ps[, j] <- probs[j] * dnorm(x, mean = mu_s[j], sd = sqrt(sigma_s[j]))
}
ps <- ps / rowSums(ps)
sigma_s_p <- sigma_s
for(j in seq(num))
{
sigma_s[j] <- sum( ps[, j] * (x - mu_s[j])^2) / sum(ps[, j])
mu_s[j] <- sum(x * ps[, j]) / sum(ps[, j])
probs[j] <- mean(ps[, j])
}
if (max(abs(sigma_s_p - sigma_s)) < epsilon)
{
break
}
}
return (list(mu = mu_s, sd = sqrt(sigma_s), prob = probs))
}
上述封裝的函數(shù)gmm
用以估計高斯混合模型的參數(shù),包括各個混合成分的均值mu
戈咳,標(biāo)準(zhǔn)差sd
驹马,混合成分的概率prob
。
用gmm
估計前面提到的數(shù)據(jù)x
gmm(x, mean = c(0, 1), sd = c(1, 1))
## $mu
## [1] 0.9749062 6.9999548
##
## $sd
## [1] 0.9415230 0.9913026
##
## $prob
## [1] 0.2469457 0.7530543
在R
語言中除秀,可以通過mixtools
包實(shí)現(xiàn)上述的EM算法估計過程糯累。
首先載入mixtools
require(mixtools)
mixtools
的normalmixEM
可以實(shí)現(xiàn)高斯混合模型的參數(shù)估計。
em <- normalmixEM(x, mu = c(0, 1), sigma = c(1, 1), sd.constr = c(1, 1))
## number of iterations= 6
估計的結(jié)果中册踩,lambda
含有混合比例泳姐,mu
是混合成分的均值。
print(em$lambda)
## [1] 0.2471721 0.7528279
print(em$mu)
## [1] 0.9777237 7.0008419
從上面的結(jié)果可知暂吉,normalmixEM
的估計結(jié)果與前面編寫的程序估計出的參數(shù)一致胖秒。
plot(em, whichplots = 2)
同時缎患,返回的em
變量,含有許多有用的信息
str(em)
## List of 9
## $ x : num [1:1000] 6.179 0.0063 6.6927 1.7511 -0.5092 ...
## $ lambda : num [1:2] 0.247 0.753
## $ mu : num [1:2] 0.978 7.001
## $ sigma : num [1:2] 1 1
## $ loglik : num -1955
## $ posterior : num [1:1000, 1:2] 6.14e-07 1.00 2.78e-08 1.00 1.00 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : NULL
## .. ..$ : chr [1:2] "comp.1" "comp.2"
## $ all.loglik: num [1:7] -15574 -2260 -1955 -1955 -1955 ...
## $ restarts : num 0
## $ ft : chr "normalmixEM"
## - attr(*, "class")= chr "mixEM"
后驗概率是一個$n \times k$的矩陣阎肝,是每個觀測值由各個混合成分產(chǎn)生的概率挤渔,可以據(jù)此得到每個觀測值的可能類別。
label <- c("head", "tail")[apply(em$posterior, 1, which.max)]
數(shù)據(jù)真正的標(biāo)簽在y
中风题,可以得到混淆矩陣
xtabs( ~ y + label)
## label
## y head tail
## head 247 1
## tail 0 752
248個head判导,有1被標(biāo)記為tail
,標(biāo)記錯誤沛硅。
可以進(jìn)一步查看該觀測值
x[y != label]
## [1] 4.390371
該值更靠近tail
眼刃,所以高斯混合模型的結(jié)果判定為tail
也不足為奇。
參考文獻(xiàn)
[1]. http://rstudio-pubs-static.s3.amazonaws.com/1001_3177e85f5e4840be840c84452780db52.html
[2]. https://en.wikibooks.org/wiki/Data_Mining_Algorithms_In_R/Clustering/Expectation_Maximization_(EM)