R/LogitNormal.R

Defines functions LogitNormal

Documented in LogitNormal

#' (Weighted) MLE of Logit-Normal Distribution
#' 
#' Logit-Normal distribution is characterized by the following probability density function,
#' \deqn{f(x;\mu, \sigma) = \frac{1}{\sigma \sqrt{2\pi}} \frac{1}{x(1-x)} \exp \left\lbrace - \frac{(\textrm{logit}(x)-\mu)^2}{2\sigma^2} \right\rbrace}
#' where the domain is \eqn{x \in \mathbf{R}} with parameters for location \eqn{\mu \in \mathbf{R}} and dispersion \eqn{\sigma^2 \in (0,\infty)}. 
#' \eqn{\textrm{logit}(x)} is a logit function, i.e., \eqn{\textrm{logit}(x) = \log(x/(1-x))}.
#' 
#' @param x a length-\eqn{n} vector of values in \eqn{(0,1)}.
#' @param weight a length-\eqn{n} weight vector. If set as \code{NULL}, it gives an equal weight, leading to standard MLE.
#' 
#' @return a named list containing (weighted) MLE of \describe{
#' \item{mu}{location \eqn{\mu}.}
#' \item{sigma}{standard deviation \eqn{\sigma}.}
#' }
#' 
#' @examples
#' #  generate data from Unif(0,1)
#' x = stats::runif(100)
#' 
#' #  fit unweighted
#' LogitNormal(x)
#' 
#' \dontrun{
#' # put random weights to see effect of weights
#' niter = 1000
#' ndata = 200
#' 
#' # generate data as above and fit unweighted MLE
#' x    = stats::runif(ndata)
#' xmle = LogitNormal(x)
#' 
#' # iterate
#' vec.mu  = rep(0,niter)
#' vec.sig = rep(0,niter)
#' for (i in 1:niter){
#'   # random weight
#'   ww = abs(stats::rnorm(ndata))
#' 
#'   MLE = LogitNormal(x, weight=ww)
#'   vec.mu[i]  = MLE$mu
#'   vec.sig[i] = MLE$sigma
#'   if ((i%%10) == 0){
#'     print(paste0(" iteration ",i,"/",niter," complete.."))
#'   }
#' }
#' 
#' # distribution of weighted estimates + standard MLE
#' opar <- par(no.readonly=TRUE)
#' par(mfrow=c(1,2))
#' hist(vec.mu,  main="location 'mu'")
#' abline(v=xmle$mu, lwd=3, col="red")
#' hist(vec.sig, main="dispersion 'sigma'")
#' abline(v=xmle$sigma, lwd=3, col="blue")
#' par(opar)
#' } 
#' 
#' @author Kisung You
#' @export
LogitNormal <- function(x, weight=NULL){
  #############################################
  # Preprocessing
  # inputs
  x = handle_cts_bdd("LogitNormal", x, lower=0, upper=1, include.boundary = FALSE)
  nx = length(x)
  weight = handle_weight("LogitNormal", weight, nx)
  
  # others
  maceps  = 10*.Machine$double.eps
  
  #############################################
  # Optimize : DEoptim
  fopt.LogitNormal <- function(pars){
    # parameters
    sig = pars[1]
    mu  = pars[2]
    
    # MLE
    loglkd = -(((log(x) - log(1-x)) - mu)^2)/(2*(sig^2)) -log(x) -log(1-x) - log(sig)
    return(-sum(loglkd*weight))
  }
  sol = DEoptim::DEoptim(fopt.LogitNormal, lower=c(maceps, -1e+5), upper=c(1e+5,1e+5), 
                         control=DEoptim::DEoptim.control(trace=FALSE))$optim$bestmem
  
  #############################################
  # Return
  output = list()
  output$sigma = as.double(sol[1])
  output$mu  = as.double(sol[2])
  return(output)
}
kyoustat/T4mle documentation built on March 26, 2020, 12:09 a.m.