R语言卡方分布自由度极大似然估计(MLE)报错问题求解
问题原因
- 函数名大小写不匹配:R语言大小写敏感,你定义的似然函数名为
loglikfun,调用maxLik时错误传入了首字母大写的Loglikfun,导致函数调用异常,出现无意义计算结果。 - 手写对数似然公式符号错误:你的代码中括号配对错误,将原本需要减去的
n*log(gamma(param[1]/2))项误变为加项,使得似然函数会随自由度k增大持续上升,优化器会向无穷大方向迭代,最终得到7496171这类完全偏离真实值的结果,迭代过程中gamma函数值过大也会触发NaN报错。 - 边界条件处理不完善:自由度小于等于0时返回NA的规则,部分优化器无法正确识别,容易导致迭代跑飞。
解决建议
- 修正函数名大小写错误,保证调用的函数名与定义完全一致。
- 优先使用R内置函数计算对数似然,避免手写公式出错,代码更简洁可靠:
loglikfun <- function(param) { k <- param[1] # 自由度必须为正,不符合时返回极小似然值 if (k <= 0) return(-1e9) return(sum(dchisq(x = X, df = k, log = TRUE))) }
- 如果你需要手写公式实现,可按正确的卡方分布对数似然修正代码:
卡方分布正确对数似然公式为:
$l(k) = \left(\frac{k}{2}-1\right)\sum\ln(x_i) - \frac{1}{2}\sum x_i - \frac{nk}{2}\ln2 - n\ln\Gamma\left(\frac{k}{2}\right)$
loglikfun <- function(param) { k <- param[1] if (k <= 0) return(-1e9) return( (k/2 - 1)*sum(log(X)) - sum(X)/2 - (n*k/2)*log(2) - n*log(gamma(k/2)) ) }
- 优化初始值设置:可以将初始值设为样本均值(卡方分布的均值等于自由度k),提升收敛稳定性:
mle <- maxLik(loglikfun, start = c(df = mean(X)))
修正后运行代码即可得到接近真实值3的估计结果,不会再出现NaN报错和异常估计值。
内容的提问来源于stack exchange,提问作者SebastianBerko
相关产品推荐
相关产品推荐

