为什么这个逻辑 GAM 拟合得这么差?

机器算法验证 r 物流 广义加法模型 黄土 毫克CV
2022-04-06 07:29:16

我正在尝试使用 mgcv::gam 创建一个逻辑回归模型,我认为这是一个简单的决策边界,但我构建的模型表现很差。使用 locfit::locfit 在相同数据上构建的局部回归模型很容易找到边界。我想在我的真实模型中添加额外的参数回归器,所以我不想切换到纯粹的局部回归。

我想了解为什么 GAM 无法拟合数据,以及是否有方法可以指定可以更好地执行的平滑。

这是一个简化的、可重现的示例:

基本事实是 1 = 点位于单位圆内,如果在单位圆外则为 0

例如 z = 1 如果 sqrt(x^2 + y^2) <= 1,否则为 0

观察到的数据是嘈杂的,既有误报也有误报

根据点的笛卡尔坐标,构建逻辑回归以预测点是否在圆内。

局部回归可以很好地找到边界(50% 的概率轮廓非常接近单位圆),但逻辑 GAM 始终高估相同概率带的圆的大小。

library(ggplot2)
library(locfit)
library(mgcv)
library(plotrix)

set.seed(0)
radius <- 1 # actual boundary
n <- 10000 # data points
jit <- 0.5 # noise factor

# Simulate random data, add polar coordinates
df <- data.frame(x=runif(n,-3,3), y=runif(n,-3,3))
df$r <- with(df, sqrt(x^2+y^2))
df$theta <- with(df, atan(y/x))

# Noisy indicator for inside the boundary
df$inside <- with(df, ifelse(r < radius + runif(nrow(df),-jit,jit),1,0))

# Plot data, shows ragged edge
(ggplot(df, aes(x=x, y=y, color=inside)) + geom_point() + coord_fixed() + xlim(-4,4) + ylim(-4,4))

在此处输入图像描述

### Model boundary condition using x,y coordinates

### local regression finds the boundary pretty accurately
m.locfit <- locfit(inside ~ lp(x,y, nn=0.3), data=df, family="binomial")
plot(m.locfit, asp=1, xlim=c(-2,-2,2,2))
draw.circle(0,0,1, border="red")

在此处输入图像描述

### But GAM fits very poorly, also tried with fx=TRUE but didn't help
m.gam <- gam(inside ~ s(x,y), data=df, family=binomial)
plot(m.gam, trans=plogis, se=FALSE, rug=FALSE)
draw.circle(0,0,1, border="red")

在此处输入图像描述

### gam.check doesn't indicate a problem with the model itself
gam.check(m.gam)

Method: UBRE   Optimizer: outer newton
full convergence after 8 iterations.
Gradient range [5.41668e-10,5.41668e-10]
(score -0.815746 & scale 1).
Hessian positive definite, eigenvalue range [0.0002169789,0.0002169789].

Basis dimension (k) checking results. Low p-value (k-index<1) may
indicate that k is too low, especially if edf is close to k'.

           k'    edf k-index p-value
s(x,y) 29.000 13.795   0.973    0.08

#### Try using polar coordinates

### Again, locfit works well
m.locfit2 <- locfit(inside ~ lp(r, nn=0.3), data=df, family="binomial")
plot(m.locfit2)
abline(v=1, col="red")

在此处输入图像描述

### But GAM misses again
m.gam2 <- gam(inside ~ s(r, k=50), data=df, family=binomial)
plot(m.gam2, se=FALSE, rug=FALSE, trans=plogis)
abline(v=1, col="red")

在此处输入图像描述

### Can also plot gam on link scale for alternate view
plot(m.gam2, se=FALSE, rug=FALSE)
abline(v=1, col="red")

在此处输入图像描述

gam.check(m.gam2)

Method: UBRE   Optimizer: outer newton
full convergence after 4 iterations.
Gradient range [-3.29203e-08,-3.29203e-08]
(score -0.8240065 & scale 1).
Hessian positive definite, eigenvalue range [7.290233e-05,7.290233e-05].

Basis dimension (k) checking results. Low p-value (k-index<1) may
indicate that k is too low, especially if edf is close to k'.

         k'    edf k-index p-value
s(r) 49.000 10.537   0.979    0.06
1个回答

在评估模型拟合时,您忽略了模型截距。plot方法显示拟合样条,但模型包含参数常数项,就像标准逻辑回归模型中的截距一样。

相反,使用该方法从拟合模型中预测predict()区间内位置网格上的位置。例如:

m.gam <- gam(inside ~ te(x, y), data=df, family=binomial, method = "REML")
locs <- with(df,
             data.frame(x = seq(min(x), max(x), length = 100),
                        y = seq(min(y), max(y), length = 100)))
pred <- expand.grid(locs)
pred <- transform(pred,
                  fitted = predict(m.gam, newdata = pred, type = "response"))
contour(locs$x, locs$y, matrix(pred$fitted, ncol = 100))
draw.circle(0, 0, 1, border="red")

这使

在此处输入图像描述

使用te()平滑器似乎比s()我使用的要好一些,method = "REML"因为这有助于解决基于 GCV/UBRE 的选择中的目标函数可能变得平坦(因此这些方法可能不够平滑)的情况,以防这是这里的问题。