Caret 包 - 使用平滑和线性预测器交叉验证 GAM
Caret package - cross-validating GAM with both smooth and linear predictors
我想使用插入符号交叉验证 GAM 模型。我的 GAM 模型有一个二元结果变量,纬度和经度坐标对的各向同性平滑,然后是线性预测变量。使用 mgcv 时的典型语法是:
gam1 <- gam( y ~ s(lat , long) + x1 + x2, family = binomial(logit) )
我不太确定如何使用插入符号中的训练函数指定此模型。这或多或少是我的语法:
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))
问题是我只想平滑经度和纬度,并将 x1 和 x2 视为线性。
谢谢!
看到有人在mgcv
外面用mgcv
很有意思。经过一些研究,我在这里让你感到沮丧:使用 mgcv
和 caret
是一个坏主意,至少在 caret
.
当前的支持下是这样
让我问你几个基本问题,如果你使用 caret
:
- 如何指定结数以及样条基础 class 以获得平滑函数?
- 如何指定二维平滑函数?
- 如何用
te
或 ti
指定张量乘积样条?
- 如何调整平滑参数?
如果你想知道caret::train
对method = "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时的classic形式
为此,您失去了对 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
是高斯分布的,不过这个没关系;它不会影响 caret
与 mgcv
的工作方式。
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)
看到了吗?除了 "additive, univariate",它还将 mgcv::s
的所有内容保留为默认值:默认值 bs = "tp"
、默认值 k = 10
等
我想使用插入符号交叉验证 GAM 模型。我的 GAM 模型有一个二元结果变量,纬度和经度坐标对的各向同性平滑,然后是线性预测变量。使用 mgcv 时的典型语法是:
gam1 <- gam( y ~ s(lat , long) + x1 + x2, family = binomial(logit) )
我不太确定如何使用插入符号中的训练函数指定此模型。这或多或少是我的语法:
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))
问题是我只想平滑经度和纬度,并将 x1 和 x2 视为线性。
谢谢!
看到有人在mgcv
外面用mgcv
很有意思。经过一些研究,我在这里让你感到沮丧:使用 mgcv
和 caret
是一个坏主意,至少在 caret
.
让我问你几个基本问题,如果你使用 caret
:
- 如何指定结数以及样条基础 class 以获得平滑函数?
- 如何指定二维平滑函数?
- 如何用
te
或ti
指定张量乘积样条? - 如何调整平滑参数?
如果你想知道caret::train
对method = "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时的classic形式
为此,您失去了对 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
是高斯分布的,不过这个没关系;它不会影响 caret
与 mgcv
的工作方式。
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)
看到了吗?除了 "additive, univariate",它还将 mgcv::s
的所有内容保留为默认值:默认值 bs = "tp"
、默认值 k = 10
等