如何在 R 中使用 constrOptim 设置限制?

机器算法验证 r 最大似然 优化 界限
2022-03-27 03:11:08

我正在使用 constrOptim 来最小化对数似然函数以进行参数的最大似然估计。

我希望设置参数的界限,但不了解可行性区域的 constrOptim 定义。

可行区域由 ui %*% theta - ci >= 0 定义

我有一组带边界的参数 [lower, upper]

a[0,5]  ie 0<a<5
b[0,Inf]
c[0,Inf]
e[0,1]

theta (starting values) = c(1, 1, 0.01,0.1)

这些参数边界的ui(约束矩阵 (kxp))和ci(长度为 k 的约束向量)是什么?

有没有一种直接的方法可以从上限和下限列表中获取uici值?

2个回答

这是一个我们可以用来说明uiand的示例,ci为简洁起见,删除了一些无关的输出。它使正态分布的对数似然最大化。在第一部分中,我们使用带有框约束的 optim 函数,在第二部分中,我们使用带有相同框约束版本的 constrOptim 函数。

# function to be optimized
> foo.unconstr <- function(par, x) -sum(dnorm(x, par[1], par[2], log=TRUE))

> x <- rnorm(100,1,1)

> optim(c(1,1), foo.unconstr, lower=c(0,0), upper=c(5,5), method="L-BFGS-B", x=x)
$par
[1] 1.147652 1.077654

$value
[1] 149.3724

> 
> # constrOptim example
> 
> ui <- cbind(c(1,-1,0,0),c(0,0,1,-1))
> ui
     [,1] [,2]
[1,]    1    0
[2,]   -1    0
[3,]    0    1
[4,]    0   -1
> ci <- c(0, -5, 0, -5)
> 
> constrOptim(c(1,1), foo.unconstr, grad=NULL, ui=u1, ci=c1, x=x)
$par
[1] 1.147690 1.077712

$value
[1] 149.3724

... blah blah blah ...

outer.iterations
[1] 2

$barrier.value
[1] -0.001079475

> 

如果您查看 ui 矩阵并想象乘以要优化的参数向量,将其称为,您会看到结果有四行,第一行是,第二,第三行和第四个减去 ci 向量并对每一行显然,将第二个和第四个约束乘以 -1 并将常数移动到右侧可以得到θθ1θ1θ2θ20θ10θ1+50θ20θ2+50θ15θ25,上限约束。

只需将您自己的值替换为 ci 向量并将适当的列(如果有)添加到 ui 向量即可获得所需的框约束集。

您的约束有两种类型,第一个已经是正确的形式(并且矩阵只是单位矩阵),而其他的可以写为 然后是并且θiaiθibiuiθibiuiIncib

# Constraints
bounds <- matrix(c(
  0,5,
  0,Inf,
  0,Inf,
  0,1
), nc=2, byrow=TRUE)
colnames(bounds) <- c("lower", "upper")

# Convert the constraints to the ui and ci matrices
n <- nrow(bounds)
ui <- rbind( diag(n), -diag(n) )
ci <- c( bounds[,1], - bounds[,2] )

# Remove the infinite values
i <- as.vector(is.finite(bounds))
ui <- ui[i,]
ci <- ci[i]

# Constrained minimization
f <- function(u) sum((u+1)^2)
constrOptim(c(1,1,.01,.1), f, grad=NULL, ui=ui, ci=ci)

我们可以检查约束矩阵是如何解释的ciui

# Print the constraints
k <- length(ci)
n <- dim(ui)[2]
for(i in seq_len(k)) {
  j <- which( ui[i,] != 0 )
  cat(paste( ui[i,j], " * ", "x[", (1:n)[j], "]", sep="", collapse=" + " ))
  cat(" >= " )
  cat( ci[i], "\n" )
}
# 1 * x[1] >= 0 
# 1 * x[2] >= 0 
# 1 * x[3] >= 0 
# 1 * x[4] >= 0 
# -1 * x[1] >= -5 
# -1 * x[4] >= -1 

中的一些算法optim允许您直接指定下限和上限:这可能更容易使用。