[英]Maximum-Likelihood Estimation of three parameter reverse Weibull model implementation in R
I'm implementing a Maximum-Likelihood estimation in R for a three parameter reverse Weibull model and have some troubles to get plausible results, which include: Bad optimization results, unwanted optimx behaviour.我正在 R 中为三参数反向 Weibull 模型实现最大似然估计,但在获得合理结果时遇到了一些麻烦,其中包括:优化结果不佳、不想要的 optimx 行为。 Beside these I wonder, how I could make use of parscale in this model.除了这些,我想知道如何在这个模型中使用 parscale。
Here is my implementation attempt:这是我的实现尝试:
To generate data I use the probabilty integral transform:为了生成数据,我使用概率积分变换:
#Generate N sigma*RWei(alph)-mu distributed points
gen.wei <- function(N, theta) {
alph <- theta[1]
mu <- theta[2]
sigma <- theta[3]
return(
mu - sigma * (- log (runif(N)))**(1/alph)
)
}
Now I define the Log-Likelihood and negative Log-Likelihood to use optimx optimization:现在我定义对数似然和负对数似然来使用 optimx 优化:
#LL----
ll.wei <- function(theta,x) {
N <- length(x)
alph <- theta[1]
mu <- theta[2]
sigma <- theta[3]
val <- sum(ifelse(
x <= mu,
log(alph/sigma) + (alph-1) * log( (mu-x)/sigma) - ( (mu-x)/sigma)**(alph-1),
-Inf
))
return(val)
}
#Negative LL----
nll.wei <- function(theta,x) {
return(-ll.wei(theta=theta, x=x))
}
Afterwards I define the analytical gradient of the negative LL.然后我定义负 LL 的解析梯度。 Remark: There are points at which the negative LL isn't differentiable (the upper end-point mu)备注:有一些点是负 LL 不可微的(上端点 mu)
gradnll.wei <- function(theta,x) {
N <- length(x)
alph <- theta[1]
mu <- theta[2]
sigma <- theta[3]
argn <- (mu-x)/sigma
del.alph <- sum(ifelse(x <= mu,
1/alph + log(argn) - log(argn) * argn**(alph-1),
0
))
del.mu <- sum(ifelse(x <= mu,
(alph-1)/(mu-x) - (alph-1)/sigma * argn**(alph-2),
0))
del.sigma <- sum(ifelse(x <= mu,
((alph-1)*argn**(alph-1)-alph)/sigma,
0))
return (-c(del.alph, del.mu, del.sigma))
}
Finally I try to optimize using the optimx package and the methods Nelder-Mead (derivative free) and BFGS (my LL is kinda smooth, there's just one point, which is problematic).最后,我尝试使用 optimx 包和方法 Nelder-Mead(无导数)和 BFGS(我的 LL 有点平滑,只有一点,这是有问题的)进行优化。
#MLE for Weibull
mle.wei <- function(start,sample) {
optimx(
par=start,
fn = nll.wei,
gr = gradnll.wei,
method = c("BFGS"),
x = sample
)
}
theta.s <- c(4,1,1/2) #test for parameters
sample <- gen.wei(100, theta.s) #generate 100 data points distributed like theta.s
mle.wei(start=c(8,4, 2), sample) #MLE Estimation
To my surprise I get the following error:令我惊讶的是,我收到以下错误:
Error in optimx.check(par, optcfg$ufn, optcfg$ugr, optcfg$uhess, lower, :
Cannot evaluate function at initial parameters
I checked manually: Both nll and gradnll are finite at the initial parameters... If i switch to optim instead of optim x I get a result, but a pretty bad one:我手动检查: nll 和 gradnll 在初始参数上都是有限的......如果我切换到 optim 而不是 optim x我得到一个结果,但一个非常糟糕的结果:
$par
[1] 8.178674e-01 9.115766e-01 1.745724e-06
$value
[1] -1072.786
$counts
function gradient
574 100
$convergence
[1] 1
$message
NULL
So it doesn't converge.所以不会收敛。 If I don't supply the gradient to BFGS, there isn't a result.如果我不向 BFGS 提供梯度,就没有结果。 If I use Nelder-Mead instead:如果我改用 Nelder-Mead:
$par
[1] 1.026393e+00 9.649121e-01 9.865624e-18
$value
[1] -3745.039
$counts
function gradient
502 NA
$convergence
[1] 1
$message
NULL
So it is also very bad...所以也很不好...
My questions are:我的问题是:
Thank you very much in advance!非常感谢您提前!
Re 3: That's kind of a bug in optimx
, but one that's hard to avoid.回复 3:这是optimx
的一个错误,但很难避免。 It uses x
as a variable name when calculating a numerical gradient;它在计算数值梯度时使用x
作为变量名; you also use it as an "additional parameter" to your functions.您还可以将其用作函数的“附加参数”。 You can work around that by renaming your argument, eg call it xdata
in your functions.你可以通过重命名你的参数来解决这个问题,例如在你的函数中调用它xdata
。
Re 1 & 2: There are several techniques to handle boundary problems in optimization. Re 1 & 2:有几种技术可以处理优化中的边界问题。 Setting to a big constant value tends not to work: if the optimizer goes out of bounds, it finds the objective function really flat.设置一个大的常数值往往不起作用:如果优化器越界,它会发现目标函数非常平坦。 If the exact boundary is legal, then pushing the parameter to the boundary and adding a penalty sometimes works.如果确切的边界是合法的,那么将参数推到边界并添加惩罚有时会起作用。 If the exact boundary is illegal, you might be able to reflect: eg if mu > 0 is a requirement, sometimes replacing mu by abs(mu) in the objective function gets things to work.如果确切的边界是非法的,您可能能够反映:例如,如果 mu > 0 是一个要求,有时在目标函数中用 abs(mu) 替换 mu 会使事情起作用。 Sometimes the best solution is to get rid of the boundary by transforming the parameters.有时最好的解决方案是通过变换参数来摆脱边界。
Edited to add some more details:编辑以添加更多详细信息:
For this problem, it looks to me as though transformations of the parameters might work.对于这个问题,在我看来,参数的转换可能有效。 I think alpha
and sigma
must both be positive.我认为alpha
和sigma
必须都是正数。 Setting alpha <- exp(theta[1])
and sigma <- exp(theta[3])
will guarantee that.设置alpha <- exp(theta[1])
和sigma <- exp(theta[3])
将保证这一点。 Limits on mu
are harder, but I think mu > max(xdata)
is needed, so mu <- max(xdata) + exp(theta[2])
should keep it in bounds.对mu
限制更难,但我认为mu > max(xdata)
是必需的,因此mu <- max(xdata) + exp(theta[2])
应该将其保持在界限内。 Of course, making these changes messes up your gradient formula and starting values.当然,进行这些更改会弄乱您的渐变公式和起始值。
As to resources: I'm afraid I don't know any.至于资源:恐怕我不知道。 This advice is based on years of painful experience.这个建议是基于多年的痛苦经验。
https://web.ncf.ca/nashjc/optimx202112/ has a version of the package that deals with at least some variable clashes in the dot args. https://web.ncf.ca/nashjc/optimx202112/有一个版本的包,至少可以处理点参数中的一些变量冲突。
There are some separate cleanups to be done before this goes on CRAN, but the package should be more or less robust at the moment.在 CRAN 上执行此操作之前,需要进行一些单独的清理工作,但目前该包应该或多或少是健壮的。
JN江南
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.