R中高斯和均匀的混合物

时间:2015-03-18 23:07:52

标签: r mixture-model

我试图融合高斯和均匀分布的混合物 在R中只取得了有限的成功。

我依靠flexmix提供EM框架,我适合 组件使用略微适应的匹配时刻版本 来自fitdistrplus包的估算工具。 (改编只是一个 用加权版本替换样本均值和方差。)

由于我对flexmix并不十分熟悉,因此代码(如下)是完全正确的 黑客攻击。

看起来整体分布的重量太少了。

非常感谢任何有关如何改善健身的帮助。

首先是示例

生成玩具数据

a <- rnorm(10000)
b <- runif(10000, min=1, max=5)
c <- c(a,b) + 10
testdata <- data.frame(c=c)

sample data

理想的契合度

comp1 <- 0.5*dnorm(testdata$c, mean=10)
comp2 <- 0.5*dunif(testdata$c, min=11, max=15)

ideal fit

契合

fit <- flexmix(c~1, data=testdata, k=2,
               model=FLXMCnormplusunifw(),
               cluster=as.integer(testdata$c < 12)+1)

fit

功能

## adapted from the 'fitdistrplus' package
fitnorm_w <- function(data, weights) {
  library("Hmisc")
  n <- length(data)
  m <- weighted.mean(data, weights)
  v <- wtd.var(data, weights, normwt = TRUE)

  list(mean=m, sd=sqrt(v))
}
## adapted from the 'fitdistrplus' package
fitunif_w <- function(data, weights) {
  library("Hmisc")
  n <- length(data)
  m <- weighted.mean(data, weights)
  v <- wtd.var(data, weights, normwt = TRUE)

  min1 <- m - sqrt(3*v)
  max1 <- m + sqrt(3*v)

  list(min=min1,
       max=max1)
}

## generate needed S4 class for flexmix -- "norm"
FLXMCnorm1w <- function (formula = . ~ .)
{
  z <- new("FLXMC", weighted = TRUE, formula = formula, dist = "norm",
           name = "model-based univariate norm clustering")
  z@defineComponent <- expression({
    logLik <- function(x, y) dnorm(y, mean = mean, sd = sd,
                                    log = TRUE)
    predict <- function(x, ...) matrix(mean, nrow = nrow(x),
                                       ncol = 1, byrow = TRUE)
    new("FLXcomponent",
        parameters = list(mean = as.vector(mean), sd = as.vector(sd)),
        df = df, logLik = logLik, predict = predict)
  })
  z@fit <- function(x, y, w, ...) {
    ##browser()
    para <- fitnorm_w(as.vector(y), as.vector(w))
    para$df <- 2
    with(para, eval(z@defineComponent))
  }
  z
}

## generate needed S4 class for flexmix -- "unif"
FLXMCunif1w <- function (formula = . ~ .)
{
  z <- new("FLXMC", weighted = TRUE, formula = formula, dist = "unif",
           name = "model-based univariate uniform clustering")
  z@defineComponent <- expression({
    logLik <- function(x, y) dunif(y, min = min, max = max,
                                   log = TRUE)
    predict <- function(x, ...) matrix(runif(nrow(x), min=min, max=max),
                                       nrow = nrow(x), ncol = 1, byrow = TRUE)
    new("FLXcomponent",
        parameters = list(min = as.vector(min), max = as.vector(max)),
        df = df, logLik = logLik, predict = predict)
  })
  z@fit <- function(x, y, w, ...) {
    ##browser()
    para <- fitunif_w(as.vector(y), as.vector(w))
    para$df <- 2
    with(para, eval(z@defineComponent))
  }
  z
}


## ---------------------------------- ##
## the norm+uniform flexmix class     ##
## ---------------------------------- ##

setClass("FLXMCnormplusunifw", contains = "FLXMC")
##
FLXMCnormplusunifw <- function(formula = . ~ ., ...)
{
  new("FLXMCnormplusunifw", FLXMCnorm1w(formula, ...),
      name = paste("FLXMCnormplusunifw" , sep=":"))
}
##
setMethod("FLXremoveComponent", signature(model = "FLXMCnormplusunifw"),
          function(model , nok, ...)
          {
            if (1 %in% nok) as(model , "FLXMC") else model
          })
##
setMethod("FLXmstep", signature(model = "FLXMCnormplusunifw"),
          function(model , weights , ...)
          {
            ##browser()
            comp.1 <- FLXMCunif1w()
            c(list(comp.1@fit(model@x, model@y, weights[, -1,drop=FALSE])),
              FLXmstep(as(model , "FLXMC"), weights[, 1, drop=FALSE]))
          })

0 个答案:

没有答案