11# # EM for Beta Mixture Models (BMM) with Nc components
22
3- EM_bmm_ab <- function (x , Nc , mix_init , Ninit = 50 , verbose = FALSE , Niter.max = 500 , tol , Neps , eps = c(w = 0.005 , a = 0.005 , b = 0.005 ), constrain_gt1 = TRUE ) {
3+ EM_bmm_ab <- function (
4+ x ,
5+ Nc ,
6+ mix_init ,
7+ Ninit = 50 ,
8+ verbose = FALSE ,
9+ Niter.max = 500 ,
10+ tol ,
11+ Neps ,
12+ eps = c(w = 0.005 , a = 0.005 , b = 0.005 ),
13+ constrain_gt1 = TRUE
14+ ) {
415 N <- length(x )
516 assert_that(N + Nc > = Ninit )
617
@@ -11,12 +22,20 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
1122 # # ensures proper handling during fit.
1223 x0 <- x == 0
1324 if (any(x0 )) {
14- message(" Detected " , sum(x0 ), " value(s) which are exactly 0.\n To avoid numerical issues during EM such values are moved to smallest eps on machine." )
25+ message(
26+ " Detected " ,
27+ sum(x0 ),
28+ " value(s) which are exactly 0.\n To avoid numerical issues during EM such values are moved to smallest eps on machine."
29+ )
1530 x [x0 ] <- .Machine $ double.eps
1631 }
1732 x1 <- x == 1
1833 if (any(x1 )) {
19- message(" Detected " , sum(x1 ), " value(s) which are exactly 1.\n To avoid numerical issues during EM such values are moved to one minus smallest eps on machine." )
34+ message(
35+ " Detected " ,
36+ sum(x1 ),
37+ " value(s) which are exactly 1.\n To avoid numerical issues during EM such values are moved to one minus smallest eps on machine."
38+ )
2039 x [x1 ] <- 1 - .Machine $ double.eps
2140 }
2241
@@ -32,7 +51,10 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
3251 # # abmEst[,1] <- 1/Nc
3352 # # assume that the sample is ordered randomly
3453 ind <- seq(1 , N - Nc , length = Ninit )
35- knnInit <- list (mu = matrix (0 , nrow = Nc , ncol = 1 ), p = rep(1 / Nc , times = Nc ))
54+ knnInit <- list (
55+ mu = matrix (0 , nrow = Nc , ncol = 1 ),
56+ p = rep(1 / Nc , times = Nc )
57+ )
3658 for (k in seq(Nc )) {
3759 knnInit $ mu [k , 1 ] <- mean(x [ind + k - 1 ])
3860 }
@@ -52,7 +74,11 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
5274 cmin <- which.min(KNN $ p )
5375 muInit [cmin ] <- sum(KNN $ p * KNN $ center )
5476 # # muInit[cmin] <- mean(x) ## could be considered here
55- nInit [cmin ] <- pmax(muInit [cmin ] * (1 - muInit [cmin ]) / var(x ) - 1 , 1 , na.rm = TRUE )
77+ nInit [cmin ] <- pmax(
78+ muInit [cmin ] * (1 - muInit [cmin ]) / var(x ) - 1 ,
79+ 1 ,
80+ na.rm = TRUE
81+ )
5682 # # Nmax <- max(2, max(nInit))
5783 # # ensure n is positive for each cluster; if this is not the
5884 # # case, sample uniformly from the range of n we have
@@ -126,7 +152,11 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
126152 traceMix <- list ()
127153 traceLli <- c()
128154 Dlli <- Inf
129- runMixPar <- array (- Inf , dim = c(Neps , 3 , Nc ), dimnames = list (NULL , rownames(mixEstPar ), NULL ))
155+ runMixPar <- array (
156+ - Inf ,
157+ dim = c(Neps , 3 , Nc ),
158+ dimnames = list (NULL , rownames(mixEstPar ), NULL )
159+ )
130160 runOrder <- 0 : (Neps - 1 )
131161 Npar <- Nc + 2 * Nc
132162 if (Nc == 1 ) Npar <- Npar - 1
@@ -160,10 +190,14 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
160190
161191 trig_n <- trigamma(n )
162192
163- grad1 <- 2 * sqTerm1 * (trigamma(ab [1 ]) * ab [1 ] - trig_n * ab [1 ]) -
193+ grad1 <- 2 *
194+ sqTerm1 *
195+ (trigamma(ab [1 ]) * ab [1 ] - trig_n * ab [1 ]) -
164196 2 * sqTerm2 * (trig_n * ab [1 ])
165197
166- grad2 <- - 2 * sqTerm1 * (trig_n * ab [2 ]) +
198+ grad2 <- - 2 *
199+ sqTerm1 *
200+ (trig_n * ab [2 ]) +
167201 2 * sqTerm2 * (trigamma(ab [2 ]) * ab [2 ] - trig_n * ab [2 ])
168202
169203 c(grad1 , grad2 )
@@ -182,7 +216,14 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
182216 a <- mixEst [2 , ]
183217 b <- mixEst [3 , ]
184218 # # lli <- sweep( sweep(Lx, 2, a - 1, "*", check.margin=FALSE) + sweep(LxC, 2, b - 1, "*", check.margin=FALSE), 2, log(w) + lgamma(a + b) - lgamma(a) - lgamma(b), "+", check.margin=FALSE)
185- lli <- sweep(sweep(Lx , 2 , a - 1 , " *" , check.margin = FALSE ) + sweep(LxC , 2 , b - 1 , " *" , check.margin = FALSE ), 2 , log(w ) - lbeta(a , b ), " +" , check.margin = FALSE )
219+ lli <- sweep(
220+ sweep(Lx , 2 , a - 1 , " *" , check.margin = FALSE ) +
221+ sweep(LxC , 2 , b - 1 , " *" , check.margin = FALSE ),
222+ 2 ,
223+ log(w ) - lbeta(a , b ),
224+ " +" ,
225+ check.margin = FALSE
226+ )
186227 # # lli <- t(matrix(log(mixEst[1,]) + dbeta(xRep, mixEst[2,], mixEst[3,], log=TRUE), nrow=Nc))
187228
188229 # # ensure that the log-likelihood does not go out of numerical
@@ -202,15 +243,36 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
202243 Dlli <- (traceLli [iter + 1 ] - traceLli [iter - 1 ]) / 2
203244 }
204245 if (Nc > 1 ) {
205- smean <- apply(runMixPar [order(runOrder ), , , drop = FALSE ], c(2 , 3 ), function (x ) mean(abs(diff(x ))))
246+ smean <- apply(
247+ runMixPar [order(runOrder ), , , drop = FALSE ],
248+ c(2 , 3 ),
249+ function (x ) mean(abs(diff(x )))
250+ )
206251 eps.converged <- sum(sweep(smean , 1 , eps , " -" ) < 0 )
207252 } else {
208- smean <- apply(runMixPar [order(runOrder ), - 1 , , drop = FALSE ], c(2 , 3 ), function (x ) mean(abs(diff(x ))))
253+ smean <- apply(
254+ runMixPar [order(runOrder ), - 1 , , drop = FALSE ],
255+ c(2 , 3 ),
256+ function (x ) mean(abs(diff(x )))
257+ )
209258 eps.converged <- sum(sweep(smean , 1 , eps [- 1 ], " -" ) < 0 )
210259 }
211260 if (is.na(eps.converged )) eps.converged <- 0
212261 if (verbose ) {
213- message(" Iteration " , iter , " : log-likelihood = " , lliCur , " ; Dlli = " , Dlli , " ; converged = " , eps.converged , " / " , Npar , " \n " , sep = " " )
262+ message(
263+ " Iteration " ,
264+ iter ,
265+ " : log-likelihood = " ,
266+ lliCur ,
267+ " ; Dlli = " ,
268+ Dlli ,
269+ " ; converged = " ,
270+ eps.converged ,
271+ " / " ,
272+ Npar ,
273+ " \n " ,
274+ sep = " "
275+ )
214276 }
215277 if (checkTol & Dlli < tol ) {
216278 break
@@ -250,7 +312,13 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
250312 # # Default would be Nelder-Mead
251313 Lest <- optim(theta , bmm_ml(c1 [i ], c2 [i ]))
252314 if (Lest $ convergence != 0 & Lest $ value > 1E-4 ) {
253- warning(" Warning: Component" , i , " in iteration" , iter , " had convergence problems!" )
315+ warning(
316+ " Warning: Component" ,
317+ i ,
318+ " in iteration" ,
319+ iter ,
320+ " had convergence problems!"
321+ )
254322 }
255323 if (constrain_gt1 ) {
256324 mixEst [2 : 3 , i ] <- 1 + pmax(exp(Lest $ par ), c(1E-8 , 1E-8 ))
@@ -297,6 +365,11 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
297365
298366# ' @export
299367print.EMbmm <- function (x , ... ) {
300- cat(" EM for Beta Mixture Model\n Log-Likelihood = " , logLik(x ), " \n\n " , sep = " " )
368+ cat(
369+ " EM for Beta Mixture Model\n Log-Likelihood = " ,
370+ logLik(x ),
371+ " \n\n " ,
372+ sep = " "
373+ )
301374 NextMethod()
302375}
0 commit comments