R 对于交互模型,手动编码的泊松对数似然函数返回与glm不同的结果
我已经编写了自己的泊松似然函数,但它返回的值与具有特定数据交互作用的模型的glm有很大不同。请注意,该函数从我尝试过的所有其他数据中,以及在没有与该数据交互的情况下,为模型吐出与glm完全相同的结果R 对于交互模型,手动编码的泊松对数似然函数返回与glm不同的结果,r,regression,glm,poisson,R,Regression,Glm,Poisson,我已经编写了自己的泊松似然函数,但它返回的值与具有特定数据交互作用的模型的glm有很大不同。请注意,该函数从我尝试过的所有其他数据中,以及在没有与该数据交互的情况下,为模型吐出与glm完全相同的结果 > # Log likelihood function > llpoi = function(X, y){ + # Ensures X is a matrix + if(class(X) != "matrix") X = as.matrix(X) + # Ensures th
> # Log likelihood function
> llpoi = function(X, y){
+ # Ensures X is a matrix
+ if(class(X) != "matrix") X = as.matrix(X)
+ # Ensures there's a constant
+ if(sum(X[, 1]) != nrow(X)) X = cbind(1, X)
+ # A useful scalar that I'll need below
+ k = ncol(X)
+ ## Function to be maximized
+ FUN = function(par, X, y){
+ # beta hat -- the parameter we're trying to estimate
+ betahat = par[1:k]
+ # mu hat -- the systematic component
+ muhat = X %*% betahat
+ # Log likelihood function
+ sum(muhat * y - exp(muhat))
+ }
+ # Optimizing
+ opt = optim(rep(0, k), fn = FUN, y = y, X = X, control = list(fnscale = -1), method = "BFGS", hessian = T)
+ # Results, including getting the SEs from the hessian
+ cbind(opt$par, sqrt(diag(solve(-1 * opt$hessian))))
+ }
>
> # Defining inputs
> y = c(2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 3, 1, 1, 3, 2, 2, 2, 3, 1, 2, 4, 3, 3, 3, 1, 3, 0, 2, 1, 2, 4, 1, 2, 0, 2, 1, 2, 1, 4, 1, 2, 0)
> x1 = c(8, 1, 0, 3, 3, 3, 5, 4, 0.4, 1.5, 2, 1, 1, 7, 2, 3, 0, 2, 1.5, 5, 1, 4, 5.5, 6, 3, 3, 2, 0.5, 5, 10, 3, 22, 20, 3, 20, 10, 15, 25, 15, 6, 3.5, 5, 18, 2, 15.0, 16, 24)
> x2 = c(12, 12, 12, 16, 12, 12, 12, 12, 12, 12, 12, 12, 9, 9, 12, 9, 12, 12, 9, 16, 9, 6, 12, 9, 9, 12, 12, 12, 12, 14, 14, 14, 9, 12, 9, 12, 3, 12, 9, 6, 12, 12, 12, 12, 12, 12, 9)
>
> # Results
> withmyfun = llpoi(cbind(x1, x2, x1 * x2), y)
> round(withmyfun, 2)
[,1] [,2]
[1,] 0.96 0.90
[2,] -0.05 0.09
[3,] -0.02 0.08
[4,] 0.00 0.01
> withglm = glm(y ~ x1 + x2 + x1 * x2, family = "poisson")
> round(summary(withglm)$coef[, 1:2], 2)
Estimate Std. Error
(Intercept) 1.08 0.90
x1 -0.07 0.09
x2 -0.03 0.08
x1:x2 0.00 0.01
这是特定于数据的吗?这是与生俱来的吗
优化过程,最终会与glm产生更大的分歧,而我只是不幸地得到了这些数据?这是使用method=“BFGS”进行optim的函数吗?通过重新缩放右侧变量,结果会有很大改善
> library(data.table)
> setDT(tmp)
> tmp[, x1 := scale(x1)][, x2 := scale(x2)]
>
>
> withmyfun = with(tmp, llpoi(cbind(x1, x2, x1 * x2), y))
> withmyfun
[,1] [,2]
[1,] 0.57076392 0.1124637
[2,] -0.19620040 0.1278070
[3,] -0.01509032 0.1169019
[4,] 0.05636459 0.1380611
>
> withglm = glm(y ~ x1 + x2 + x1 * x2, family = "poisson", data = tmp)
> summary(withglm)$coef[, 1:2]
Estimate Std. Error
(Intercept) 0.57075132 0.1124641
x1 -0.19618199 0.1278061
x2 -0.01507467 0.1169034
x1:x2 0.05636934 0.1380621
>
因此,我的建议是,在llpoi
中,在使用optim
对数据进行处理之前,有一个过程来规范化变量,并在函数返回值之前重新缩放估计值。您的示例数据的范围太大,导致系数的估计值非常小。这个问题变得更糟,因为相对平坦的似然面,因为不重要的变量
注意:
除截距外,您可以从中获得非常接近的输出。我所说的标准化是这样的
llpoi = function(X, y){
# Ensures X is a matrix
if(class(X) != "matrix") X = as.matrix(X)
# Ensures there's a constant
if(sum(X[, 1]) != nrow(X)) X = cbind(1, X)
# A useful scalar that I'll need below
avgs <- c(0, apply(X[, 2:ncol(X)], 2, mean))
sds <- c(1, apply(X[, 2:ncol(X)], 2, sd))
X<- t((t(X) - avgs)/sds)
k = ncol(X)
## Function to be maximized
FUN = function(par, X, y){
# beta hat -- the parameter we're trying to estimate
betahat = par[1:k]
# mu hat -- the systematic component
muhat = X %*% betahat
# Log likelihood function
sum(muhat * y - exp(muhat))
}
# Optimizing
opt = optim(rep(0, k), fn = FUN, y = y, X = X, control = list(fnscale = -1), method = "BFGS", hessian = T)
# Results, including getting the SEs from the hessian
cbind(opt$par, sqrt(diag(solve(-1 * opt$hessian))))/sds
}
llpoi=函数(X,y){
#确保X是一个矩阵
如果(类(X)!=“矩阵”)X=as.matrix(X)
#确保有一个常数
if(sum(X[,1])!=nrow(X))X=cbind(1,X)
#下面我需要一个有用的标量
avgs经过大量研究,我了解到这两个结果不同,因为glm背后的主力glm.fit通过牛顿-拉斐逊方法优化函数,而我在llpoi函数中使用了BFGS。BFGS更快,但精度更低。在大多数情况下,这两个结果非常相似,但在表面积为正如amatsuo_net正确指出的那样,oo平坦或有太多的最大值,因为BFGS使用的爬升算法将被卡住。这个问题可能会从交叉验证堆栈中得到更好的答案,因为这个问题更多的是关于统计上下文而不是R代码。你是对的。我可以移动这个问题吗,或者只有主持人可以这样做?我会复制并粘贴到那里。我有一些编辑能力,但没有那么多。对不起!我不太关心模型拟合(事实上我知道这是一个非常糟糕的模型),而更关心glm的可复制性。我想了解为什么结果如此不同,以及如何最小化差异,而不管数据如何。“如何最小化差异”是我要说的。你需要规范化(我指的是标准化)如果你想得到类似于glm
的结果,那么在函数中使用optim
之前的数据。我在代码中展示的是,通过标准化函数外的变量,你可以得到非常相似的结果,因为对于这种格式良好的数据,llpoi
表现得与glm
一样好。为什么你需要标准化数据可以在其他地方找到(例如),但请注意,除非用户在调用glm之前也对数据进行标准化,包括llpoi中的标准化不会解决我的问题;glm和llpoi的结果不会几乎相同,这正是我所寻求的。