r - 自定义链接功能适用于 GLM 但不适用于 mgcv GAM

标签 r regression glm gam mgcv

如果答案很明显,我深表歉意,但我花了很多时间尝试在 mgcv.gam 中使用自定义链接功能

简而言之,

  • 我想使用包 psyphy 中经过修改的 probit 链接(我想用psyphy.probit_2asym,我叫它custom_link)
  • 我可以使用此链接创建一个 {stats}family 对象,并在 glm 的“family”参数中使用它。

    m <- glm(y~x, family=binomial(link=custom_link), ... )

  • 它在用作 {mgcv}gam 的参数时不起作用

    m <- gam(y~s(x), family=binomial(link=custom_link), ... )

    我收到错误 Error in fix.family.link.family(family) : link not recognised

我不明白这个错误的原因,如果我指定标准 link=probit,glm 和 gam 都可以工作.

所以我的问题可以概括为:

这个适用于 glm 但不适用于 gam 的自定义链接缺少什么?

如果您能提示我应该做什么,在此先感谢您。


链接功能

probit.2asym <- function(g, lam) {
    if ((g < 0 ) || (g > 1))
        stop("g must in (0, 1)")
    if ((lam < 0) || (lam > 1))
        stop("lam outside (0, 1)")
    linkfun <- function(mu) {
        mu <- pmin(mu, 1 - (lam + .Machine$double.eps))
        mu <- pmax(mu, g + .Machine$double.eps)
        qnorm((mu - g)/(1 - g - lam))
        }
    linkinv <- function(eta) {
        g + (1 - g - lam) * 
         pnorm(eta)
        }
    mu.eta <- function(eta) {
        (1 - g - lam) * dnorm(eta)      }
    valideta <- function(eta) TRUE
    link <- paste("probit.2asym(", g, ", ", lam, ")", sep = "")
    structure(list(linkfun = linkfun, linkinv = linkinv, 
    mu.eta = mu.eta, valideta = valideta, name = link), 
    class = "link-glm")
}

最佳答案

如您所知,glm 采用迭代重新加权最小二乘法 拟合迭代。 gam 的早期版本通过拟合迭代惩罚重新加权最小二乘法 对此进行了扩展,这是由 gam.fit 函数完成的。这在某些情况下称为性能迭代

自 2008 年以来(或者甚至更早),gam.fit3 基于所谓的外部迭代 已将 gam.fit 替换为gam 默认值。这种变化确实需要家庭的一些额外信息,关于这些信息你可以阅读 ?fix.family.link

两次迭代的主要区别在于系数beta的迭代和平滑参数lambda的迭代是否嵌套。

  • 性能迭代采用嵌套方式,对于 beta 的每次更新,都会执行一次 lambda 迭代;
  • 外部迭代将这 2 次迭代完全分开,其中对于 beta 的每次更新,lambda 的迭代都进行到最后直到收敛。

显然,外部迭代更稳定并且不太可能出现收敛失败。

gam 有一个参数 optimizer。默认采用optimizer = c("outer", "newton"),即外层迭代的newton方法;但是如果你设置optimizer = "perf",它会进行性能迭代。


所以,在上面的概述之后,我们有两个选择:

  • 仍然使用外部迭代,但扩展您自定义的链接功能;
  • 使用性能迭代与 glm 保持一致。

我很懒惰,所以将演示第二种方法(实际上我对采用第一种方法不太自信)


可重现的例子

你没有提供可重现的例子,所以我准备了一个如下。

set.seed(0)
x <- sort(runif(500, 0, 1))    ## covariates (sorted to make plotting easier)
eta <- -4 + 3 * x * exp(x) - 2 * log(x) * sqrt(x)   ## true linear predictor
p <- binomial(link = "logit")$linkinv(eta)    ## true probability (response)
y <- rbinom(500, 1, p)    ## binary observations

table(y)    ## a quick check that data are not skewed
#  0   1 
#271 229 

我将采用您打算使用的函数 probit.2asymg = 0.1lam = 0.1:

probit2 <- probit.2asym(0.1, 0.1)

par(mfrow = c(1,3))

## fit a glm with logit link
glm_logit <- glm(y ~ x, family = binomial(link = "logit"))
plot(x, eta, type = "l", main = "glm with logit link")
lines(x, glm_logit$linear.predictors, col = 2)

## glm with probit.2asym
glm_probit2 <- glm(y ~ x, family = binomial(link = probit2))
plot(x, eta, type = "l", main = "glm with probit2")
lines(x, glm_probit2$linear.predictors, col = 2)

## gam with probit.2aysm
library(mgcv)
gam_probit2 <- gam(y ~ s(x, bs = 'cr', k = 3), family = binomial(link = probit2),
                   optimizer = "perf")
plot(x, eta, type = "l", main = "gam with probit2")
lines(x, gam_probit2$linear.predictors, col = 2)

enter image description here

我对s(x) 使用了自然三次样条基cr,至于单变量平滑,薄板样条的默认设置是不必要的。我还设置了一个小的基础维度 k = 3(对于三次样条曲线不能更小)因为我的玩具数据接近线性并且不需要大的基础维度。更重要的是,这似乎可以防止我的玩具数据集的性能迭代收敛失败。

关于r - 自定义链接功能适用于 GLM 但不适用于 mgcv GAM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39793085/

相关文章:

r - 合并数据并接收大量数据丢失

r - 如何强制在较新版本的 R 上安装较旧的软件包?

为 R 中的多个变量替换组内的特定 chr 值

r - 将一系列回归的结果依次存储到数据框中

python - pytorch 如何计算简单线性回归模型的梯度?

r - glm() 模型的交叉验证

r - 在 R 中调整 plotmo::plot_glmnet 的顶轴标题和标签图

r - 根据 bootstrap GLM 列表计算 LC50

r - GLM 逻辑回归的有效起始值错误

java - 趋势线(回归,曲线拟合)java库