R 为什么我的GLM预测值是周期性的?

R 为什么我的GLM预测值是周期性的?,r,graph,statistics,glm,mle,R,Graph,Statistics,Glm,Mle,我写了一个二项式回归模型来预测火成岩的流行程度,v,在一个考古遗址,基于靠近一条河流,river\u dist,但是当我使用predict()函数时,我得到的是奇怪的周期性结果,而不是我所期望的曲线。作为参考,我的数据: v n river_dist 1 102 256 1040 2 1 11 720 3 19 24 475 4 12 15 611 我适合这种模式: library(bbmle) m_r <-

我写了一个二项式回归模型来预测火成岩的流行程度,
v
,在一个考古遗址,基于靠近一条河流,
river\u dist
,但是当我使用predict()函数时,我得到的是奇怪的周期性结果,而不是我所期望的曲线。作为参考,我的数据:

    v   n river_dist
1 102 256       1040
2   1  11        720
3  19  24        475
4  12  15        611
我适合这种模式:

library(bbmle)
m_r <- mle2(ig$v ~ dbinom(size=ig$n, prob = 1/(1+exp(-(a + br * river_dist)))),
    start = list(a = 0, br = 0), data = ig)
那很好。但当我试图预测新的价值观时,我得到了这种奇怪的价值循环:

newdat <- data.frame(river_dist=seq(min(ig$river_dist), max(ig$river_dist),len=100))
newdat$v <- predict(m_r, newdata=newdat, type="response")
plot(v~river_dist, data=ig, col="red4")
lines(v ~ river_dist, newdat, col="green4", lwd=2)

为什么值会像那样上下循环,在绘制图形时会产生疯狂的尖峰?

为了使
新数据
正常工作,您必须将变量指定为“原始”值,而不是使用
$

library(bbmle)
m_r <- mle2(v ~ dbinom(size=n, prob = 1/(1+exp(-(a + br * river_dist)))),
    start = list(a = 0, br = 0), data = ig)
??(
bbmle:mle2
更一般,但
glm
更稳健。)(另外:将两个参数拟合到四个数据点在理论上是很好的,但您不应该尝试将结果推得太远……特别是,glm/MLE的许多默认结果都是渐进的…)

实际上,在仔细检查MLE拟合与GLM的对应关系时,我意识到默认方法(“BFGS”,出于历史原因)实际上并没有给出正确的答案(!);切换到
method=“Nelder-Mead”
可以改善情况。将
control=list(parscale=c(a=1,br=0.001))
添加到参数列表中,或缩放河流距离(例如,从“1m”到“100m”或“1km”作为单位),也可以解决问题

m_r <- mle2(v ~ dbinom(size=n,
        prob = 1/(1+exp(-(a + br * river_dist)))),
            start = list(a = 0, br = 0), data = ig,
            method="Nelder-Mead")
pframe <- data.frame(river_dist=seq(500,1000,length=51),n=1)
pframe$prop <- predict(m_r, newdata=pframe, type="response")
CIs <- lapply(seq(nrow(ig)),
              function(i) prop.test(ig[i,"v"],ig[i,"n"])$conf.int)
ig2 <- data.frame(ig,setNames(as.data.frame(do.call(rbind,CIs)),
              c("lwr","upr")))
library(ggplot2); theme_set(theme_bw())
ggplot(ig2,aes(river_dist,v/n))+
    geom_point(aes(size=n)) +
    geom_linerange(aes(ymin=lwr,ymax=upr)) +
    geom_smooth(method="glm",
                method.args=list(family=binomial),
              aes(weight=n))+
    geom_line(data=pframe,aes(y=prop),colour="red")

m\r当您传递四行数据时,预测似乎以四个步骤循环——因此它可能是循环n。对于预测,你可以做
plogis(tcrossprod(coef(m_r),cbind(1,newdat$river_dist))
但这并不能回答你的问题。。。。因此,请尝试使用
newdat$n=1
。ps当你使用
数据=
时,你不需要使用
ig$
,也就是说,使用
mle2(v~dbinom(size=n,
@user20650,并不是有意窃取此信息。(对于如此清晰的评论,你不妨发布一个答案…)您如何确定
parscale
值?这是在拟合模型一次后完成的,然后在第二次运行时进行缩放还是?您可以运行并重新缩放,或者只是将
parscale
设置为大约
1/
哇,这太棒了!谢谢!我怀疑我最初的R stats讲师教我们mle2,所以我们不得不思考明确说明我们的起始值;很高兴了解未来的glm函数。这张图很漂亮!你是个救命恩人。旁注后续:从500-1000米处运行预测值,而不是我的数据中的实际最小值和最大值(475和1040米)有什么好处吗?我想是口味/偏好的问题。
library(bbmle)
m_r <- mle2(v ~ dbinom(size=n, prob = 1/(1+exp(-(a + br * river_dist)))),
    start = list(a = 0, br = 0), data = ig)
glm(cbind(v,n-v) ~ river_dist, data=ig, family=binomial) 
m_r <- mle2(v ~ dbinom(size=n,
        prob = 1/(1+exp(-(a + br * river_dist)))),
            start = list(a = 0, br = 0), data = ig,
            method="Nelder-Mead")
pframe <- data.frame(river_dist=seq(500,1000,length=51),n=1)
pframe$prop <- predict(m_r, newdata=pframe, type="response")
CIs <- lapply(seq(nrow(ig)),
              function(i) prop.test(ig[i,"v"],ig[i,"n"])$conf.int)
ig2 <- data.frame(ig,setNames(as.data.frame(do.call(rbind,CIs)),
              c("lwr","upr")))
library(ggplot2); theme_set(theme_bw())
ggplot(ig2,aes(river_dist,v/n))+
    geom_point(aes(size=n)) +
    geom_linerange(aes(ymin=lwr,ymax=upr)) +
    geom_smooth(method="glm",
                method.args=list(family=binomial),
              aes(weight=n))+
    geom_line(data=pframe,aes(y=prop),colour="red")