@@ -469,3 +469,231 @@ pois_mean_GP_opt_obj_gradient = function(theta,x,s,beta,sigma2,n){
469469pois_mean_GP_obj = function (x ,s ,beta ,sigma2 ,m ,v ){
470470 return (sum(x * m - s * exp(m + v / 2 )- log(sigma2 )/ 2 - (m ^ 2 + v - 2 * m * beta + beta ^ 2 )/ 2 / sigma2 + log(v )/ 2 ))
471471}
472+
473+
474+
475+
476+
477+
478+
479+ # '@title Smooth over-dispersed Poisson sequence
480+ # '@param x data vector
481+ # '@param maxiter,tol max iteration and tolerance for stopping it.
482+ # '@param Eb_init,sigma2_init initial values of smooth mean and nugget effect.
483+ # '@examples
484+ # ' set.seed(12345)
485+ # ' n=2^9
486+ # ' sigma=0.5
487+ # ' mu=c(rep(0.3,n/4), rep(3, n/4), rep(10, n/4), rep(0.3, n/4))
488+ # ' x = rpois(n,exp(log(mu)+rnorm(n,sd=sigma)))
489+ # ' fit = pois_smooth_split(x,maxiter=30)
490+ # ' plot(x,col='grey80')
491+ # ' lines(exp(fit$Eb))
492+ # ' fit$sigma2
493+ # ' plot(fit$obj)
494+ # '@details The problem is
495+ # '\deqn{x_i\sim Poisson(\exp(\mu_i)),}
496+ # '\deqn{\mu_i\sim N(b_i,\sigma^2),}
497+ # '\deqn{\b_i\sim g(.).}
498+ # '@export
499+
500+ pois_smooth_split = function (x ,
501+ s = NULL ,
502+ Eb_init = NULL ,
503+ sigma2_init = NULL ,
504+ est_sigma2 = TRUE ,
505+ maxiter = 100 ,
506+ tol = 1e-5 ,
507+ filter.number = 1 ,
508+ family = ' DaubExPhase' ,
509+ verbose = FALSE ,
510+ printevery = 10 ,
511+ ebnm_params = list (mode = 0 ),
512+ optim_method = ' L-BFGS-B' ){
513+
514+ n = length(x )
515+ if (is.null(s )){
516+ s = 1
517+ }
518+ if (length(s )== 1 ){
519+ s = rep(s ,n )
520+ }
521+ if (is.null(Eb_init )){
522+ Eb = log(runmed(x / s ,1 + 2 * min((n - 1 )%/% 2 , ceiling(0.1 * n )))+ 0.01 )
523+ }else {
524+ Eb = Eb_init
525+ }
526+ if (is.null(sigma2_init )){
527+ sigma2 = var(log(x / s + 0.01 )- Eb )
528+ }else {
529+ sigma2 = sigma2_init
530+ }
531+
532+ W = (t(wavethresh :: GenW(n ,filter.number ,family )))[- 1 ,]
533+
534+ mu_pm = rep(0 ,n )
535+ mu_pv = rep(1 / n ,n )
536+ obj = - Inf
537+
538+ for (iter in 1 : maxiter ){
539+ # get m, s^2
540+ opt = optim(c(mu_pm ,log(mu_pv )),
541+ fn = pois_mean_GP_opt_obj ,
542+ gr = pois_mean_GP_opt_obj_gradient ,
543+ x = x ,
544+ s = s ,
545+ beta = Eb ,
546+ sigma2 = sigma2 ,
547+ n = n ,
548+ method = optim_method )
549+ mu_pm = opt $ par [1 : n ]
550+ mu_pv = exp(opt $ par [(n + 1 ): (2 * n )])
551+ qb = smash_dwt(x = mu_pm ,
552+ sigma = sqrt(sigma2 ),
553+ filter.number = filter.number ,
554+ family = family ,
555+ ebnm_params = ebnm_params ,W = W )
556+ Eb = qb $ mu.est
557+ Eb2 = qb $ mu.est.var + Eb ^ 2
558+ # get sigma2
559+ if (est_sigma2 ){
560+ sigma2 = mean(mu_pm ^ 2 + mu_pv + Eb2 - 2 * mu_pm * Eb )
561+ }
562+
563+
564+ # calc obj
565+ obj [iter + 1 ] = pois_smooth_split_obj(x ,s ,mu_pm ,mu_pv ,Eb ,Eb2 ,sigma2 ,qb $ dKL )
566+
567+ if (verbose ){
568+ if (iter %% printevery == 0 ){
569+ print(paste(" Done iter" ,iter ," obj =" ,obj [iter + 1 ]))
570+ }
571+
572+ }
573+
574+ if ((obj [iter + 1 ]- obj [iter ])< tol ){
575+ break
576+ }
577+
578+ }
579+ return (list (Emean = exp(mu_pm + mu_pv / 2 ),
580+ Vmean = exp(mu_pv - 1 )* exp(2 * mu_pm + mu_pv ),
581+ Emu = mu_pm ,
582+ Vmu = mu_pv ,
583+ Eb = Eb ,
584+ Eb2 = Eb2 ,
585+ sigma2 = sigma2 ,
586+ obj = obj ,
587+ H = qb $ dKL + sum(log(2 * pi * mu_pv )/ 2 - log(2 * pi * sigma2 )/ 2 - (mu_pm ^ 2 + mu_pv - 2 * mu_pm * Eb + Eb2 )/ 2 / sigma2 )))
588+ }
589+
590+ pois_smooth_split_obj = function (x ,s ,m ,s2 ,Eb ,Eb2 ,sigma2 ,KLb ){
591+ return (sum(x * m - s * exp(m + s2 / 2 )+ log(s2 )/ 2 - log(sigma2 )/ 2 - (m ^ 2 + s2 - 2 * m * Eb + Eb2 )/ 2 / sigma2 )+ KLb )
592+ }
593+
594+
595+
596+ # '@title Empirical Bayes wavelet smoothing via DWT
597+ # '@description Smooth homogeneous Gaussian data.
598+ # '@param x data
599+ # '@param sigma known standard error
600+ # '@param filter.number,family wavelet family and filter number as in wavethresh package
601+ # '@param ebnm_params a list of `ebnm` parameters
602+ # '@param W the dwt matrix for calc posterior variance. Remove the first row which is all 1/sqrt(n)
603+ # '@return a list of
604+ # ' \item{mu.est:}{posterior mean}
605+ # ' \item{mu.est.var:}{posterior variance}
606+ # ' \item{loglik:}{log likelihood}
607+ # ' \item{dKL:}{KL divergence between g(the prior) and q(the posterior)}
608+ # '@import wavethresh
609+ # '@import ebnm
610+ # '@export
611+ smash_dwt = function (x ,sigma ,filter.number = 1 ,
612+ family = " DaubExPhase" ,
613+ ebnm_params = list (mode = 0 ),W = NULL ){
614+
615+ n = length(x )
616+ J = log(n ,2 )
617+ if (ceiling(J )!= floor(J )){
618+ stop(' Length of x must be power of 2' )
619+ }
620+ if (is.null(ebnm_params )){
621+ ebnm_params = ebnm_params_default()
622+ }else {
623+ temp = ebnm_params_default()
624+ for (i in 1 : length(ebnm_params )){
625+ temp [[names(ebnm_params )[i ]]] = ebnm_params [[i ]]
626+ }
627+ ebnm_params = temp
628+ }
629+ tsum = sum(x )/ sqrt(n )
630+ x.w = wd(x , filter.number = filter.number ,
631+ family = family , type = " wavelet" )
632+
633+ data.var = sigma ^ 2
634+ if (length(data.var == 1 )){
635+ data.var = rep(data.var ,n )
636+ }
637+
638+ if (is.null(W )){
639+ W = (t(GenW(n ,filter.number ,family )))[- 1 ,]
640+ }
641+
642+ if (length(sigma )== 1 ){
643+ x.w.v = rep(sigma ^ 2 ,n - 1 )
644+ tsum.var = sigma ^ 2
645+ }else {
646+ x.w.v = data.var
647+ tsum.var = x.w.v [1 ]
648+ x.w.v = x.w.v [- 1 ]
649+ }
650+
651+ dKL = 0
652+ loglik.scale = c()
653+ x.w.v.s = rep(0 , 2 ^ J - 1 )
654+ for (j in 0 : (J - 1 )) {
655+ x.pm = rep(0 , 2 ^ j )
656+ # index = (((J - 1) - j) * n + 1):((J - j) * n)
657+ index = (n - 2 ^ (j + 1 )+ 1 ): (n - 2 ^ j )
658+ x.w.j = accessD(x.w , j )
659+ x.w.v.j = x.w.v [index ]
660+ ind.nnull = (x.w.v.j != 0 )
661+
662+ a = ebnm(x.w.j [ind.nnull ],sqrt(x.w.v.j [ind.nnull ]),
663+ mode = ebnm_params $ mode ,
664+ prior_family = ebnm_params $ prior_family ,
665+ scale = ebnm_params $ scale ,
666+ g_init = ebnm_params $ g_init ,
667+ fix_g = ebnm_params $ fix_g ,
668+ output = ebnm_params $ output ,
669+ optmethod = ebnm_params $ optmethod )
670+
671+ dKL = dKL + a $ log_likelihood - Eloglik_GP(x.w.j [ind.nnull ], sqrt(x.w.v.j [ind.nnull ]),a $ posterior $ mean , a $ posterior $ mean ^ 2 + a $ posterior $ sd ^ 2 )
672+ x.pm [ind.nnull ] = a $ posterior $ mean
673+ x.pm [! ind.nnull ] = 0
674+ x.w = putD(x.w , j , x.pm )
675+ loglik.scale [j + 1 ] = a $ log_likelihood
676+ x.w.v.s [index [ind.nnull ]] = a $ posterior $ sd ^ 2
677+ x.w.v.s [index [! ind.nnull ]] = 0
678+ }
679+ mu.est = wr(x.w )
680+ loglik = sum(loglik.scale )
681+ # x.w.v.s = c(tsum.var,x.w.v.s)
682+ mu.est.var = colSums(W ^ 2 * x.w.v.s )
683+ return (list (mu.est = mu.est ,mu.est.var = mu.est.var ,loglik = loglik ,dKL = dKL ))
684+ }
685+
686+
687+
688+ Eloglik_GP = function (x , s , Et , Et2 ) {
689+ # Deal with infinite SEs:
690+ idx = is.finite(s )
691+ x = x [idx ]
692+ s = s [idx ]
693+ Et = Et [idx ]
694+ Et2 = Et2 [idx ]
695+ return (- 0.5 * sum(log(2 * pi * s ^ 2 ) + (1 / s ^ 2 ) * (Et2 - 2 * x * Et + x ^ 2 )))
696+ }
697+
698+
699+
0 commit comments