从命名列表创建函数参数(使用应用程序到stats4 :: mle)

时间:2011-09-27 16:07:51

标签: r

我应该首先说明我要做的事情:我想使用mle函数,而不必在每次我想尝试不同的模型规范时重新编写我的对数似然函数。因为mle期望一个命名的起始值列表,所以你显然不能将对数似然函数写成带参数的向量。一个简单的例子:

假设我想通过最大可能性拟合线性回归模型,首先,我忽略了我的一个预测因素:

n <- 100
df <- data.frame(x1 = runif(n), x2 = runif(n), y = runif(n))
Y <- df$y
X <- model.matrix(lm(y ~ x1, data = df))

# define log-likelihood function 
ll <- function(beta0, beta1, sigma){
  beta = matrix(NA, nrow=2, ncol=1)
  beta[,1] = c(beta0, beta1)
  -sum(log(dnorm(Y - X %*% beta, 0, sigma)))
}
library(stats4)
mle(ll, start = list(beta0=.1, beta1=.2, sigma=1)

现在,如果我想要适合不同的模型,请说:

m <- lm(y ~ x1 + x2, data = df)

我无法重新使用我的对数似然函数 - 我必须重新编写它以获得beta3参数。我想做的是:

ll.flex <- function(theta){
 # theta is a vector that I can use directly 
  ...
}

if 然后我可以以某种方式调整mle中的start参数来解释我现在的向量输入对数似然函数,或者除此之外,有一个在运行时构造对数似然函数的函数-time,比如通过构造命名的参数列表然后用它来定义函数,例如:

X <- model.matrix(lm(y ~ x1 + x2, data = df))
arguments <- rep(NA, dim(X)[2])
names(arguments) <- colnames(X)
ll.magic <- function(bring.this.to.life.as.function.arguments(arguments)){...} 

更新:

我最终编写了一个辅助函数,可以向传递的函数f添加任意数量的命名参数x1,x2,x3 ....

add.arguments <- function(f,n){
  # adds n arguments to a function f; returns that new function 
  t = paste("arg <- alist(",
  paste(sapply(1:n, function(i) paste("x",i, "=",sep="")), collapse=","),
  ")", sep="")
  formals(f) <- eval(parse(text=t))
  f
 }

这很丑陋,但它完成了工作,让我在运行中重新考虑我的对数似然函数。

4 个答案:

答案 0 :(得分:5)

您可以使用包mle2中的bbmle函数,该函数允许您将向量作为参数传递。这是一些示例代码。

# REDEFINE LOG LIKELIHOOD
ll2 = function(params){
  beta = matrix(NA, nrow = length(params) - 1, ncol = 1)
  beta[,1] = params[-length(params)] 
  sigma    = params[[length(params)]]
  minusll  = -sum(log(dnorm(Y - X %*% beta, 0, sigma)))
  return(minusll)
}

# REGRESS Y ON X1
X <- model.matrix(lm(y ~ x1, data = df))
mle2(ll2, start = c(beta0 = 0.1, beta1 = 0.2, sigma = 1), 
  vecpar = TRUE, parnames = c('beta0', 'beta1', 'sigma'))

# REGRESS Y ON X1 + X2

X <- model.matrix(lm(y ~ x1 + x2, data = df))
mle2(ll2, start = c(beta0 = 0.1, beta1 = 0.2, beta2 = 0.1, sigma = 1), 
      vecpar = TRUE, parnames = c('beta0', 'beta1', 'beta2', 'sigma'))

这会给你

Call:
mle2(minuslogl = ll2, start = c(beta0 = 0.1, beta1 = 0.2, beta2 = 0.1, 
    sigma = 1), vecpar = TRUE, parnames = c("beta0", "beta1", 
    "beta2", "sigma"))

Coefficients:
     beta0      beta1      beta2      sigma 
 0.5526946 -0.2374106  0.1277266  0.2861055

答案 1 :(得分:4)

直接使用optim可能更容易;这就是mle正在使用的东西。

ll2 <- function(par, X, Y){
  beta <- matrix(c(par[-1]), ncol=1)
  -sum(log(dnorm(Y - X %*% beta, 0, par[1])))
}
getp <- function(X, sigma=1, beta=0.1) {
  p <- c(sigma, rep(beta, ncol(X)))
  names(p) <- c("sigma", paste("beta", 0:(ncol(X)-1), sep=""))
  p
}

set.seed(5)
n <- 100
df <- data.frame(x1 = runif(n), x2 = runif(n), y = runif(n))
Y <- df$y
X1 <- model.matrix(y ~ x1, data = df) 
X2 <- model.matrix(y ~ x1 + x2, data = df)
optim(getp(X1), ll2, X=X1, Y=Y)$par
optim(getp(X2), ll2, X=X2, Y=Y)$par

输出

> optim(getp(X1), ll2, X=X1, Y=Y)$par
      sigma       beta0       beta1 
 0.30506139  0.47607747 -0.04478441 
> optim(getp(X2), ll2, X=X2, Y=Y)$par
      sigma       beta0       beta1       beta2 
 0.30114079  0.39452726 -0.06418481  0.17950760 

答案 2 :(得分:3)

它可能不是你想要的,但我会这样做:

mle2(y ~ dnorm(mu, sigma),parameters=list(mu~x1 + x2), data = df,
    start = list(mu = 1,sigma = 1))

mle2(y ~ dnorm(mu,sigma), parameters = list(mu ~ x1), data = df,
    start = list(mu=1,sigma=1))

您可能可以针对多项式调整此公式,但dmultinom可能不起作用 - 您可能需要编写一个Dmultinom(),其中包含多项式样本矩阵并返回(日志)概率。

答案 3 :(得分:0)

Ramnath提供的R代码也可以应用于optim函数,因为 它也将矢量作为参数。