我正在尝试为多项式分布建立简单的数值MLE估计。
多项式有一个约束-所有像元概率都需要加起来为一个。
通常具有此约束的方法是将一个概率重新表示为(1-其他概率之和)
但是,当我运行此命令时,在优化过程中出现了问题,对数可能为负值。
关于如何解决此问题的任何想法?我尝试使用另一个优化程序包(Rsolnp)并起作用,但是我试图使其与简单的默认R optim一起工作,以避免约束/非线性优化。
这是我的代码(我知道我可以在这种特殊情况下分析得出结果,但这是一个玩具示例,我的实际问题比这里要大)。
set.seed(1234)
test_data <- rmultinom(n = 1, size = 1000, prob = rep(1/4, 4))
N <- test_data
loglik_function <- function(theta){
output <- -1*(N[1]*log(theta[1]) + N[2]*log(theta[2]) + N[3]*log(theta[3]) + N[4]*log(1- sum(theta)))
return(output)
}
startval <- rep(0.1, 3)
my_optim <- optim(startval, loglik_function, lower = 0.0001, upper = 0.9999, method = "L-BFGS-B")
任何想法或帮助将不胜感激。谢谢
答案 0 :(得分:3)
充分抬头:我知道您问过(受限)的ML估计,但是如何使用贝叶斯方法àla Stan / rstan
做这件事。如果没有用/遗漏了点,我将删除它。
该模型只有几行代码。
library(rstan)
model_code <- "
data {
int<lower=1> K; // number of choices
int<lower=0> y[K]; // observed choices
}
parameters {
simplex[K] theta; // simplex of probabilities, one for every choice
}
model {
// Priors
theta ~ cauchy(0, 2.5); // weakly informative
// Likelihood
y ~ multinomial(theta);
}
generated quantities {
real ratio;
ratio = theta[1] / theta[2];
}
"
您可以看到使用Stan数据类型theta
在simplex
上实现单纯形约束有多么容易。在Stan语言中,simplex
使您可以轻松实现probability (unit) simplex
其中K表示参数数(此处为选择数)。
还要注意如何使用generated quantities
代码块根据参数(此处为ratio
和theta[1]
)来计算派生数量(此处为theta[2]
)。由于我们可以访问所有参数的后验分布,因此计算派生数量的分布很简单。
然后我们将模型拟合到您的test_data
fit <- stan(model_code = model_code, data = list(K = 4, y = test_data[, 1]))
并显示参数估计值的摘要
summary(fit)$summary
# mean se_mean sd 2.5% 25%
#theta[1] 0.2379866 0.0002066858 0.01352791 0.2116417 0.2288498
#theta[2] 0.26 20013 0.0002208638 0.01365478 0.2358731 0.2526111
#theta[3] 0.2452539 0.0002101333 0.01344665 0.2196868 0.2361817
#theta[4] 0.2547582 0.0002110441 0.01375618 0.2277589 0.2458899
#ratio 0.9116350 0.0012555320 0.08050852 0.7639551 0.8545142
#lp__ -1392.6941655 0.0261794859 1.19050097 -1395.8297494 -1393.2406198
# 50% 75% 97.5% n_eff Rhat
#theta[1] 0.2381541 0.2472830 0.2645305 4283.904 0.9999816
#theta[2] 0.2615782 0.2710044 0.2898404 3822.257 1.0001742
#theta[3] 0.2448304 0.2543389 0.2722152 4094.852 1.0007501
#theta[4] 0.2545946 0.2638733 0.2822803 4248.632 0.9994449
#ratio 0.9078901 0.9648312 1.0764747 4111.764 0.9998184
#lp__ -1392.3914998 -1391.8199477 -1391.3274885 2067.937 1.0013440
以及显示theta
参数的点估计和CI的图
plot(fit, pars = "theta")
maxLik
实际上,您可以使用maxLik
库提供的方法来实现约束ML估计。我发现它有点“麻烦”,因为收敛似乎对起始值和所用优化方法的变化非常敏感。
对于它的价值,这是一个可重复的示例:
library(maxLik)
x <- test_data[, 1]
为多项式分布定义对数似然函数;我在此处加入了if
语句,以防止theta < 0
情况引发错误。
loglik <- function(theta, x)
if (all(theta > 0)) sum(dmultinom(x, prob = theta, log = TRUE)) else 0
我在这里使用Nelder-Mead优化方法来找到对数似然函数的最大值。这里重要的一点是constraints
参数,它以等式A theta + B = 0
的形式实现约束,有关详细信息和示例,请参见?maxNM
。
res <- maxNM(
loglik,
start = rep(0.25, length(x)),
constraints = list(
eqA = matrix(rep(1, length(x)), ncol = length(x)),
eqB = -1),
x = x)
我们可以检查结果
summary(res)
--------------------------------------------
Nelder-Mead maximization
Number of iterations: 111
Return code: 0
successful convergence
Function value: -10.34576
Estimates:
estimate gradient
[1,] 0.2380216 -0.014219040
[2,] 0.2620168 0.012664714
[3,] 0.2450181 0.002736670
[4,] 0.2550201 -0.002369234
Constrained optimization based on SUMT
Return code: 1
penalty close to zero
1 outer iterations, barrier value 5.868967e-09
--------------------------------------------
并确认估计的总和等于1(在准确度之内)
sum(res$estimate)
#[1] 1.000077
set.seed(1234)
test_data <- rmultinom(n = 1, size = 1000, prob = rep(1/4, 4))