更新:对于一个最小的示例向下滚动(不重现相同的错误但不同的结果)
在我的实际问题之前要注意一点:我对 R 很陌生,所以我希望我说得通。我尝试使用 google 和 R 的调试功能来解决问题(尽管我对它们还不太熟悉)。
除其他外,我已阅读:
这把我带到了 Hadley Wickham 的非常好的博客,在那里我将进一步研究 R 的调试功能,他的文章: 非标准评估
我的问题
我有一个名为data的数据框,其中包含公司债券的数据以及债券的到期收益率、寿命和评级等数据。
我想使用 bbmle 包中的 mle2 函数(它是 optim 函数的包装器)来估计期限结构的模型,请参见下面的代码。然而,残差正态分布的假设是否合理尚有待商榷:
方法1:“手动”子集工作得很好:
require("bbmle")
lifeBBB <- data$life[data$Rating == "BBB"]
yieldBBB <- data$yield[data$Rating == "BBB"]
LL <- function(b0, b1, b2, lambda, mu, sigma){
Score= yieldBBB - (b0+b1*((1-exp(-lambda*lifeBBB))/(lambda*lifeBBB))+ b2*((1-exp(-lambda*lifeBBB))/(lambda*lifeBBB)-exp(-lambda*lifeBBB)))
Score = suppressWarnings(dnorm(Score, mu, sigma, log=TRUE))
-sum(Score)
}
fit <- mle2(LL, start = list(b0 = 108, b1 = -85, b2=168, lambda= 0.12, mu = -10, sigma=70),control=list(maxit = 5000))'
Call:
mle2(minuslogl = LL, start = list(b0 = 108, b1 = -85, b2 = 168,
lambda = 0.12, mu = -10, sigma = 70), control = list(maxit = 5000))
Coefficients:
b0 b1 b2 lambda mu
110.2355968 -82.7010072 167.5960478 0.1410541 -7.7644032
sigma
69.4846302
Log-likelihood: -1018.8
方法 2:当我尝试从 mle2 函数中调用子集时,会发生错误:
LL2 <- function(b0, b1, b2, lmbd, mu, sigma){
Score= yield - (b0+b1*((1-exp(-lmbd*life))/(lmbd*life))+ b2*((1-exp(-lmbd*life))/(lmbd*life)-exp(-lmbd*life)))
Score = suppressWarnings(dnorm(Score, mu, sigma, log=TRUE))
-sum(Score)
}
fit1 <- mle2(minuslogl=LL2, start = list(b0 = 108, b1 = -85, b2=168, lmbd= 0.12, mu = -10, sigma=70),method="BFGS", data=data, subset= Rating=="BBB", control=list(maxit=5000))
Error in optim(par = c(108, -85, 168, 0.12, -10, 70), fn = function (p) :
initial value in 'vmmin' is not finite
因此,由于方法 1 有效,而方法 2 应该是一种更方便的方法来做完全相同的事情,而不必为每个评级引入新变量,我认为我的代码中一定有问题。正如我所说,我尝试使用调试方法,结果在 R 机房深处的某个地方出现了完全不同的错误。
在产生的错误中,我从R Mailing list 中找到了这个,这里的问题是分数而不是整数被提供为 dbinom 分布的大小参数。但我看不出这是我的代码中的问题。
提前致谢
B.洛尔
根据要求,我尝试提出一个使用示例性数据的最小示例。最小示例不会产生错误,但会产生两组不同的估计值。这很奇怪,因为据我了解,这两个功能都应该做同样的事情
#### minmial example
require("bbmle")
## approach 1:
set.seed(23456)
Rating <- c(rep("A",38),rep("BBB",39) )
yield <- rnorm(77,0.5,15)
life <- runif(77,1,20)
exdata <- data.frame(Rating,yield,life)
lifeBBB <- exdata$life[exdata$Rating == "BBB"]
yieldBBB <- exdata$yield[exdata$Rating == "BBB"]
LL <- function(b0, b1, b2, lambda, mu, sigma){
Score= yieldBBB - (b0+b1*((1-exp(-lambda*lifeBBB))/(lambda*lifeBBB))+ b2*((1-exp(-lambda*lifeBBB))/(lambda*lifeBBB)-exp(-lambda*lifeBBB)))
Score = suppressWarnings(dnorm(Score, mu, sigma, log=TRUE))
-sum(Score)
}
fit <- mle2(LL, start = list(b0 = 100, b1 = -80, b2=160, lambda= 0.12, mu = 1, sigma=14),method ="BFGS",control=list(maxit = 5000))
### approach 2:
LL2 <- function(b0, b1, b2, lmbd, mu, sigma){
Score= exdata$yield - (b0+b1*((1-exp(-lmbd*exdata$life))/(lmbd*exdata$life))+ b2*((1-exp(-lmbd*exdata$life))/(lmbd*exdata$life)-
exp(-lmbd*exdata$life)))
Score = suppressWarnings(dnorm(Score, mu, sigma, log=TRUE)) ## assumption is that residuals are normally distributed
-sum(Score)
}
fit1 <- mle2(minuslogl=LL2, start = list(b0 = 100, b1 = -80, b2=160, lmbd= 0.12, mu = 1, sigma=14),method="BFGS", data=exdata, subset= Rating=="BBB", control=list(maxit=5000))
Call(fit):
Call:
mle2(minuslogl = LL, start = list(b0 = 100, b1 = -80, b2 = 160,
lambda = 0.12, mu = 1, sigma = 14), method = "BFGS", control = list(maxit = 5000))
Coefficients:
b0 b1 b2 lambda mu sigma
94.34166416 -85.35582080 159.76952349 -0.00283408 -4.65833584 12.94283927
Log-likelihood: -155.2
Call (fit1):
all:
mle2(minuslogl = LL2, start = list(b0 = 100, b1 = -80, b2 = 160,
lmbd = 0.12, mu = 1, sigma = 14), method = "BFGS", data = exdata,
subset = Rating == "BBB", control = list(maxit = 5000))
Coefficients:
b0 b1 b2 lmbd mu sigma
9.269496e+01 -8.600709e+01 1.586543e+02 -1.186371e-04 -6.305040e+00 1.458118e+01
Log-likelihood: -315.6