Caret包 - 通过平滑和线性预测器交叉验证GAM

时间:2017-01-15 16:37:34

标签: r r-caret cross-validation gam mgcv

我想使用插入符来交叉验证GAM模型。我的GAM模型有一个二元结果变量,纬度和经度坐标对的各向同性平滑,然后是线性预测变量。使用mgcv时的典型语法是:

gam1 <- gam( y ~ s(lat , long) + x1 + x2, family = binomial(logit) )

我不太确定如何使用插入符号中的train函数指定此模型。这或多或少是我的语法:

cv <- train(y ~ lat + long + x1 + x2, 
            data = data, 
            method = "gam", 
            family = "binomial", 
            trControl = trainControl(method = "LOOCV", number=1, repeats=), 
            tuneGrid = data.frame(method = "GCV.Cp", select = FALSE))

问题是我只想平滑lat和long,并且x1和x2被视为线性。

谢谢!

1 个答案:

答案 0 :(得分:10)

mgcv之外看到有人使用mgcv非常有趣。经过一些研究后,我来到这里是为了让你感到沮丧:将mgcvcaret一起使用是一个坏主意,至少在caret的当前支持下。

如果您使用caret

,我们只是问您几个基本问​​题
  1. 如何指定结的数量,以及平滑函数的样条基础类?
  2. 如何指定2D平滑功能?
  3. 如何使用teti
  4. 指定张量积样条
  5. 如何使用平滑参数进行调整?
  6. 如果您想知道caret::trainmethod = "gam"做了什么,请查看其拟合程序:

    getModelInfo(model = "gam", regex = FALSE)$gam$fit
    
    function(x, y, wts, param, lev, last, classProbs, ...) { 
                dat <- if(is.data.frame(x)) x else as.data.frame(x)
                modForm <- caret:::smootherFormula(x)
                if(is.factor(y)) {
                  dat$.outcome <- ifelse(y == lev[1], 0, 1)
                  dist <- binomial()
                } else {
                  dat$.outcome <- y
                  dist <- gaussian()
                }
                modelArgs <- list(formula = modForm,
                                  data = dat,
                                  select = param$select, 
                                  method = as.character(param$method))
                ## Intercept family if passed in
                theDots <- list(...)
                if(!any(names(theDots) == "family")) modelArgs$family <- dist
                modelArgs <- c(modelArgs, theDots)                 
                out <- do.call(getFromNamespace("gam", "mgcv"), modelArgs)
                out    
                }
    

    您看到modForm <- caret:::smootherFormula(x)行?那条线是关键,而其他线只是模型调用的常规构造。那么,让我们检查GAM公式caret正在构建的内容:

    caret:::smootherFormula
    
    function (data, smoother = "s", cut = 10, df = 0, span = 0.5, 
        degree = 1, y = ".outcome") 
    {
        nzv <- nearZeroVar(data)
        if (length(nzv) > 0) 
            data <- data[, -nzv, drop = FALSE]
        numValues <- sort(apply(data, 2, function(x) length(unique(x))))
        prefix <- rep("", ncol(data))
        suffix <- rep("", ncol(data))
        prefix[numValues > cut] <- paste(smoother, "(", sep = "")
        if (smoother == "s") {
            suffix[numValues > cut] <- if (df == 0) 
                ")"
            else paste(", df=", df, ")", sep = "")
        }
        if (smoother == "lo") {
            suffix[numValues > cut] <- paste(", span=", span, ",degree=", 
                degree, ")", sep = "")
        }
        if (smoother == "rcs") {
            suffix[numValues > cut] <- ")"
        }
        rhs <- paste(prefix, names(numValues), suffix, sep = "")
        rhs <- paste(rhs, collapse = "+")
        form <- as.formula(paste(y, rhs, sep = "~"))
        form
    }
    

    简而言之,它创造了附加的,单变量的光滑。这是GAM首次提出时的经典形式。

    为此,您在mgcv上失去了大量控制权,如前所列。

    为了验证这一点,让我为您的案例构建一个类似的例子:

    set.seed(0)
    dat <- gamSim(eg = 2, scale = 0.2)$data[1:3]
    dat$a <- runif(400)
    dat$b <- runif(400)
    dat$y <- with(dat, y + 0.3 * a - 0.7 * b)
    
    #            y         x         z          a         b
    #1 -0.30258559 0.8966972 0.1478457 0.07721866 0.3871130
    #2 -0.59518832 0.2655087 0.6588776 0.13853856 0.8718050
    #3 -0.06978648 0.3721239 0.1850700 0.04752457 0.9671970
    #4 -0.17002059 0.5728534 0.9543781 0.03391887 0.8669163
    #5  0.55452069 0.9082078 0.8978485 0.91608902 0.4377153
    #6 -0.17763650 0.2016819 0.9436971 0.84020039 0.1919378
    

    所以我们的目标是拟合一个模型:y ~ s(x, z) + a + b。数据y是高斯数据,但这无关紧要;它不会影响caretmgcv的合作方式。

    cv <- train(y ~ x + z + a + b, data = dat, method = "gam", family = "gaussian",
                trControl = trainControl(method = "LOOCV", number=1, repeats=1), 
                tuneGrid = data.frame(method = "GCV.Cp", select = FALSE))
    

    您可以提取最终模型:

    fit <- cv[[11]]
    

    那么它使用的公式是什么?

    fit$formula
    #.outcome ~ s(x) + s(z) + s(a) + s(b)
    

    请参阅?除了“加法,单变量”之外,它还将mgcv::s的所有内容保留为默认值:默认bs = "tp",默认k = 10等。