Выбор модели для множественной биномиальной GAM (MGCV) и / или множественной логистики c регрессии - PullRequest
0 голосов
/ 03 апреля 2020

Я пытаюсь смоделировать логистический ответ c на основе 4 непрерывных переменных из эксперимента, который я провел. Первоначально я использовал множественную регрессию и достиг довольно хорошего результата, но недавно мне предложили вместо этого использовать GAM. Я немного растерялся из-за того, как правильно сделать выбор модели для GAM, а также как интерпретировать некоторые предупреждения, которые я получаю из своей множественной регрессии GLM. Я подозреваю, что мои проблемы связаны с переоснащением, но я не знаю, как их обойти.

В основном вопрос заключается в следующем: каков наилучший / самый экономный способ моделирования этих данных?

df:

df <- structure(list(response = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                            0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                            0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0),
               V1 = c(14.2,13.67, 13.05, 14.18, 13.4, 14.12, 14.22, 14.15, 13.35, 13.67, 
                      18.58, 18.27, 18.6, 17.94, 18.38, 18.98, 18.15, 19, 18.55, 18.53, 
                      20.77, 21.65, 21.03, 21.57, 21.25, 21.63, 21.6, 21.09, 21.62, 
                      21.6, 26.23, 26.52, 25.7, 26.57, 26.6, 26.25, 26.48, 26.26, 26.25, 
                      26.4, 28.98, 29.45, 29.2, 29.65, 29.38, 28.6, 28.42, 28.95, 28.85, 
                      28.8), V2 = c(27.2, 37.98, 24.63, 32.97, 30.27, 18.66, 13.77, 
                      33.99, 15.8, 21.32, 14.21, 15.81, 35.83, 21.64, 26.93, 38.62, 
                      34.03, 18.76, 24.12, 29.67, 29.83, 33.22, 27.11, 24.92, 21.72, 
                      39.02, 12.93, 18.44, 36.34, 15.81, 13.29, 21.04, 19.05, 33.62, 
                      30.52, 16.07, 28.43, 24.97, 39.9, 37.05, 19.31, 31.3, 34.08, 
                      13.63, 25.1, 28.93, 22.36, 34.69, 39.5, 16.41), 
               V3 = c(8.06, 7.87, 7.81, 7.72, 8.04, 7.66, 7.72, 7.87, 7.72, 7.98, 7.59, 7.9, 
                      8.08, 7.64, 8.02, 7.73, 7.77, 7.74, 7.66, 7.71, 8.05, 7.68, 7.63, 
                      7.7, 7.64, 7.8, 7.7, 7.98, 7.86, 7.68, 7.65, 7.74, 7.99, 7.75, 
                      7.91, 7.64, 7.69, 7.78, 7.69, 7.66, 7.72, 7.76, 7.71, 7.88, 7.63, 
                      7.7, 7.99, 7.82, 7.75, 7.93), 
               V4 = c(362.12, 645.38, 667.54, 
                      957.44, 391.84, 818.34, 732.91, 649.05, 722.02, 406.71, 918.9, 
                      471.32, 363.77, 926.82, 385.4, 1038.91, 850.67, 715.11, 964.79, 
                      890.11, 370.51, 1078.68, 1083.7, 893.76, 1026.1, 887.29, 737.68, 
                      406.76, 690.39, 872.8, 847.26, 738.53, 397.33, 895.3, 563.93, 
                      991.17, 957.28, 734.55, 1140.5, 1199.12, 817.17, 800.5, 992.82, 
                      533.45, 1123.29, 943.25, 411.59, 745.22, 929.75, 460.82)), 
          row.names = c(NA,-50L), class = "data.frame")

Следует отметить, что при проведении экспериментов и зная о системе, я знаю, что V1 и V2 оказывают наибольшее влияние на реакцию. Вы также можете увидеть это, построив ответ только по этим переменным, поскольку все положительные ответы сгруппированы в этом двумерном пространстве. Кроме того, если взглянуть на некоторые временные сплайны, кажется, что V1 линейно связан с откликом, V2 - квадратично, V3 - совсем нет, а V4 - слабо квадратично c.

enter image description here

enter image description here

Еще одно важное замечание: V3 и V4 - это две разные меры одного и того же, поэтому они сильно коррелированы и не будут используется в любых моделях вместе.

Итак, сначала я попытался смоделировать все это в регрессии mutliple logisti c: мне посоветовали протестировать целую кучу разных моделей в моем выборе модели, поэтому я записал их в список и запустил их все в al oop:

formulas <- list(# single predictors
                 response ~ V1,
                 response ~ V2,
                 response ~ V3,
                 response ~ V4,

                 # two predictors
                 response ~ V1 + V2,
                 response ~ V1 + V3,
                 response ~ V1 + V4,
                 response ~ V2 + V3,
                 response ~ V2 + V4,

                 # three predictors
                 response ~ V1 + V2 + V3,
                 response ~ V1 + V2 + V4,

                 # start quadratic models
                 response ~  V2 + I(V2^2) + V1 + I(V1^2),
                 response ~  V2 + I(V2^2) + V1 + I(V1^2) + V3,
                 response ~  V2 + I(V2^2) + V1 + I(V1^2) + V4,
                 response ~ V1 + V2 + I(V1^2),
                 response ~ V1 + V2 + I(V1^2) + V3,
                 response ~ V1 + V2 + I(V1^2) + V4,
                 response ~ V1 + I(V1^2),
                 response ~ V1 + V2 + I(V2^2),
                 response ~ V1 + V2 + I(V2^2) + V3,
                 response ~ V1 + V2 + I(V2^2) + V4,
                 response ~  V2 + I(V2^2),
                 response ~  V2 + I(V2^2) + V1 + I(V1^2),
                 # add interactions
                 response ~ V1 + V2 + V1*V2,
                 response ~ V1 + V2 + V1*V2 + V3,
                 response ~ V1 + V2 + V1*V2 + V4,
                 # quadratic with interaction
                 response ~ V1 + V2 + V1*V2 + V3 + I(V1^2),
                 response ~ V1 + V2 + V1*V2 + V3 + I(V2^2),
                 response ~ V1 + V2 + V1*V2 + V4 + I(V1^2),
                 response ~ V1 + V2 + V1*V2 + V4 + I(V2^2)

)

# run them all in a loop, then order by AIC
selection <- purrr::map_df(formulas, ~{
  mod <- glm(.x, data= df, family="binomial")
  data.frame(formula = format(.x), 
             AIC = round(AIC(mod),2), 
             BIC = round(BIC(mod),2),
             R2adj = round(DescTools::PseudoR2(mod,which=c("McFaddenAdj")),3)
  )
})

warnings()

warnings()
# this returns a bunch of warnings about coercing the formulas into vectors, ignore those.
# however, this also lists the following for a handful of the models:
# "glm.fit: fitted probabilities numerically 0 or 1 occurred"
# which means perfect separation, but I'm not sure if this is a totally bad thing
# or not, as perfect separation actually pretty much does exist in the real data


# then we arrange by AIC and get our winning model:
selection %>% arrange(desc(AIC))


Таким образом, используя эту технику, мы находим две лучшие модели response ~ V1 + V2 + I(V2^2) + V4 и response ~ V1 + V2 + I(V2^2). Но при запуске их по одному мы получаем ошибку numerically 1 or 0 для обоих, и мы видим, что единственное различие между ними (добавленный V4) не является статистически значимым само по себе в лучшей модели. Итак ... какие мы используем ??

bestmod1 <- glm(response ~ V1 + V2 + I(V2^2) + V4,
                family="binomial",
                data=df)
summary(bestmod1)$coefficients

bestmod2 <- glm(response ~ V1 + V2 + I(V2^2),
                family="binomial",
                data=df)
summary(bestmod2)$coefficients

Метод 2: GAMs

Подобная техника здесь, перечислить все формулы и запустить в al oop.

library(mgcv)
gam_formulas <- list( # ind. main effects,
  response ~ s(V1),
  response ~ s(V2),
  response ~ s(V3),
  response ~ s(V4),

  # two variables
  response ~ s(V1) + s(V2),
  response ~ s(V1) + s(V3),
  response ~ s(V1) + s(V4),
  response ~ s(V2) + s(V3),
  response ~ s(V2) + s(V4),

  # three variables
  response ~ s(V1) + s(V2) + s(V3),
  response ~ s(V1) + s(V2) + s(V4),

  # add interactions
  response ~ te(V1, V2),
  response ~ te(V1, V2) + s(V3),
  response ~ te(V1, V2) + s(V4),
  response ~ te(V1, V3),
  response ~ te(V1, V3) + s(V2),
  response ~ te(V1, V4),
  response ~ te(V1, V4) + s(V2),                  
  response ~ te(V2, V3),
  response ~ te(V2, V3) + s(V1),
  response ~ te(V2, V4),
  response ~ te(V2, V4) + s(V1), 
  response ~ te(V2, by=V1),
  response ~ te(V1, by=V2),
  response ~ te(V2, by=V3),

  # two interactions?
  response ~ te(V1, V3) + te(V1, V2),
  response ~ te(V1, V4) + te(V1, V2),
  response ~ te(V2, V3) + te(V1, V2),
  response ~ te(V2, V4) + te(V1, V2)
)

gam_selection <- purrr::map_df(gam_formulas, ~{
  gam <- gam(.x, 
             data= df,  # always use same df
             family="binomial",
             method="REML")  # always use REML smoothing method
  data.frame(cbind(formula = as.character(list(formula(.x))),
                   round(broom::glance(gam),2),
                   R2 = summary(gam)$r.sq
  ))
})

# similarly, this gives a bunch of warnings about coercing the formulas into characters, 
# but also this, for a handful of the models, which I am guessing is an overfitting thing:
#  In newton(lsp = lsp, X = G$X, y = G$y, Eb = G$Eb, UrS = G$UrS,  ... :
#  Fitting terminated with step failure - check results carefully


gam_selection %>% arrange(desc(AIC))

но это возвращает кучу дурацких вещей, так как многие модели (даже не обязательно с подобными формулами или значениями AI C) говорят, что R2 = 1,00, и они являются формулами, которые не это имеет смысл, биологически. Почему это происходит? Что мне с этим делать? (Я знаю, что это как-то связано с использованием "REML", потому что некоторые из этих ошибок go исчезли без этой строки). По моему мнению, наиболее точным является третий из лучших, согласно значениям AI C: response ~ te(V2, by = V1), с использованием V2 в качестве сглаженной переменной и V1 в качестве линейной.

Кроме того, если присмотреться к двум лучшим играм, согласно AI C, ни одна из переменных сама по себе не является существенной (p-значения = 1 ... странно), что заставляет меня чувствовать, что я не должен использовать это.

bestgam <- gam(response ~ s(V1) + s(V2) + s(V4), 
               data= df,  # always use same df
               family="binomial",
               method="REML")
summary(bestgam)
bestgam2 <- gam(response ~ s(V1) + s(V2) + s(V3), 
               data= df,  # always use same df
               family="binomial",
               method="REML")
summary(bestgam2)
bestgam3 <- gam(response ~ te(V2, by = V1), 
                data= df,  # always use same df
                family="binomial",
                method="REML")
summary(bestgam3) # this is the one I think I should be using

По сути, я не знаю, почему я бы использовал GAM вместо GLM или наоборот, тогда как выбирать переменные и избегать переобучения в процессе. Любой совет приветствуется.

Спасибо!

...