Как изменить ось Y для многомерной модели GAM с сглаженных на фактические значения? - PullRequest
2 голосов
/ 29 мая 2019

Я использую многомерные модели GAM, чтобы больше узнать о тенденциях тумана в нескольких регионах.Туман определяется видимостью ниже определенного порога (<400 метров).Наша модель GAM используется для определения реакции видимости на диапазон метеорологических переменных.</p>

Однако сейчас моя проблема заключается в том, чтобы я действительно хотел, чтобы ось Y была фактическими наблюдениями видимости, а не сглаженными по центру. интересно интересно посмотреть, как ковариаты влияют на видимость по сравнению со средней видимостью в этом месте, но трудно сравнить это для нескольких мест, где средняя видимость отличается (и, таким образом, точка 0, в которойвидимость улучшена или уменьшена имеет мало сопоставимого значения).

Чтобы сравнить результаты по нескольким местоположениям, я пытаюсь сделать фактические наблюдения видимости по оси Y, а затем поставлю линию на пороге видимости, на который мы заинтересованы смотреть (400 м), чтобы оценить, как значения переменных предиктора ниже этого порога (например, какие температуры связаны с видимостью ниже 400 м).

Я все еще начинающий, когда дело доходит до ГАМ и R в целом,но я выяснил несколько полезных частей до сих пор.

Полезные сведения:

Попытка 1. Как извлечь подгонку для каждой переменной в модели Извлечение данных, используемых для построения плавного графика в mgcv

Попытка 2. Как использовать функцию прогнозирования для восстановления неизменяемой модели http://zevross.com/blog/2014/09/15/recreate-the-gam-partial-regression-smooth-plots-from-r-package-mgcv-with-a-little-style/

Попытка 3. Как получить некоторое подобие оси Y, которое выглядит как наблюдения видимости, используя «подогнанный» - хотя яне думаю, что это правильный подход, так как я не принимаю во внимание перехват http://gsp.humboldt.edu/OLM/R/05_03_GAM.html

смоделированные данные

install.packages("mgcv") #for gam package
require(mgcv)
install.packages("pspline")
require(pspline)


#simulated GAM data for example
dataSet <- gamSim(eg=1,n=400,dist="normal",scale=2)
visibility <- dataSet[[1]]
temperature <- dataSet[[2]]
dewpoint <- dataSet[[3]]
windspeed <- dataSet[[4]]


#Univariable GAM model
gamobj <- gam(visibility ~  s(dewpoint))
plot(gamobj, scale=0, page=1, shade = TRUE, all.terms=TRUE, cex.axis=1.5, cex.lab=1.5, main="Univariable Model: Dew Point")
summary(gamobj)
AIC(gamobj)
abline(h=0)

Неизменная модель точки росы https://imgur.com/1uzP34F

ATTEMPT 2 - функция прогнозирования с неизменяемой моделью, но без изменения оси y

#dummy var that spans length of original covariate
maxDP <-max(dewpoint)
minDP <-min(dewpoint)
DPtrial.seq <-seq(minDP,maxDP,length=3071)
DPtrial.seq <-data.frame(dewpoint=DPtrial.seq)

#predict only the DP term 
preds <- predict(gamobj, type="terms", newdata=DPtrial.seq, se.fit=TRUE)

#determine confidence intervals
DPplot <-DPtrial.seq$dewpoint
fit <-preds$fit
fit.up95 <-fit-1.96*preds$se.fit
fit.low95 <-fit+1.96*preds$se.fit

#plot
plot(DPplot, fit, lwd=3,
 main="Reconstructed Dew Point Covariate Plot")

#plot confident intervals
polygon(c(DPplot, rev(DPplot)), 
    c(fit.low95,rev(fit.up95)), col="grey",
    border=NA)

lines(DPplot, fit,  lwd=2)
rug(dewpoint) 

Реконструированный ковариатный график точки росы https://imgur.com/VS8QEcp

ATTEMPT 3 - изменено yось, использующая «подогнанный», но без учета перехвата

plot(dewpoint,fitted(gamobj), main="Fitted Response of Y (Visibility) Plotted Against Dew Point")
abline(h=mean(visibility))
rug(dewpoint)

подогнанный отклик Y, нанесенный против точки росы https://imgur.com/RO0q6Vw

В конечном счете, я хочу горизонтальную линию, где я могу исследоватьпеременная предиктордо 400 метров, а не просто среднее значение переменной отклика.Таким образом, он будет сопоставим на нескольких сайтах, где средняя видимость отличается.Самое главное, это должно быть для нескольких ковариат!

Гэвин Симпсон объяснил метод в нескольких постах, но, к сожалению, я действительно не понимаю, как бы я держал среднее значение других ковариат постоянным, как яиспользуйте функцию предсказания:

Изменение оси Y графиков plot.gam по умолчанию

Любое более глубокое объяснение метода для этого было бы очень полезно !!!

1 Ответ

1 голос
/ 29 мая 2019

Я не уверен, насколько это будет полезно, так как ваш Q немного более открыт, чем мы обычно хотели бы на SO, но здесь все в порядке.

Во-первых, я думаю, что это помогло бы подумать о моделировании переменной ответа, которая, как я полагаю, в настоящее время видна. Это будет непрерывная переменная, ограниченная 0 (возможно, данные никогда не достигнут нуля?), Которая предлагает моделировать данные как условно распределенные либо

  • гамма (family = Gamma(link = 'log')) для видимости, которая никогда не принимает значение ноль.
  • Твиди (family = tw()) для данных, которые имеют нули.

Альтернативным подходом было бы моделирование возникновения тумана; если это определено как событие <400м, то вы можете превратить все свои наблюдения в значения 0/1, чтобы они были явлением тумана или иным образом. Тогда вы бы смоделировали данные как условно распределенные Бернулли, используя <code>family = binomial().

Определившись с подходом моделирования, нам нужно смоделировать ответ. Это должно быть сделано с использованием подхода множественной регрессии с GAM, включающим несколько предикторов. Таким образом, вы можете оценить влияние каждой потенциальной переменной предиктора на ответ, одновременно контролируя влияние других предикторов. Если вы просто делаете это, используя один предиктор за раз, скажем, dewpoint, эта переменная вполне может «объяснить» изменение в данных, которое может быть связано с другим предиктором, скажем, windspeed, и вы об этом не узнаете.

Кроме того, вполне возможно взаимодействие между предикторами, которые вы захотите контролировать, если они существуют, что может быть сделано только в

Затем, чтобы, наконец, разобраться в сути вашей проблемы, применив модель с несколькими предикторами для «объяснения» видимости, вам нужно будет сделать прогноз на основе этой модели для наборов вероятных условий. Чтобы посмотреть, как видимость меняется с dewpoint в модели, где другие переменные-предикторы оказывают влияние, вам нужно зафиксировать другие переменные в некоторых разумных значениях; один из вариантов - установить для них среднее значение (или модальное значение в случае любых переменных-предикторов фактора) или другое значение, указывающее типичные значения для этой переменной. Для этого вам придется использовать свои знания предметной области.

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

Предположим, у вас нет взаимодействий и вас интересует dewpoint, но модель также включает windspeed. Средняя скорость ветра для значений, используемых для подгонки модели, может быть найдена из компонента cmX подгонянной модели. Из вас можно просто рассчитать это по наблюдаемым windpseed значениям или установить для некоторого известного числа, которое вы хотите использовать. Обозначим подогнанный m, а фрейм данных с вашими данными в нем df, тогда мы можем создать новые данные для прогнозирования в диапазоне dewpoint, при этом удерживая windspeed фиксированным.

mn.windspd <- m$cmX['windspeed']
## or
mn.windspd <- with(df, mean(windspeed))
## or set it some some value
mn.windspd <- 10 # say

Тогда вы можете сделать

preddata <- with(df,
                 expand.grid(dewpoint = seq(min(dewpoint),
                                            max(dewpoint),
                                            length = 300),
                             windspeed = mn.windspd))

Затем вы используете это, чтобы предсказать из подобранной модели:

pred <- predict(m, newdata = preddata, type = "link", se.fit = TRUE)
pred <- as.data.frame(pred)

Теперь мы хотим вернуть эти прогнозы обратно в шкалу ответов, и нам нужен доверительный интервал, поэтому мы должны сначала создать его перед обратным преобразованием:

ilink <- family(m)$linkinv
pred <- transform(pred,
                  Fitted = ilink(fit),
                  Upper  = ilink(fit + (2 * se.fit)),
                  Lower  = ilink(fit - (2 * se.fit)),
                  dewpoint = preddata = dewpoint)

Теперь вы можете визуализировать влияние dewpoint на ответ, сохраняя windspeed фиксированным.

В вашем случае вам придется расширить это, чтобы сохранить temperature константу также, но это делается таким же образом

mn.windspd <- m$cmX['windspeed']
mn.temp <- m$cmX['temperature']
preddata <- with(df,
                 expand.grid(dewpoint = seq(min(dewpoint),
                                            max(dewpoint),
                                            length = 300),
                             windspeed = mn.windspd,
                             temperature = mn.temp))

и затем выполните действия, описанные выше, чтобы сделать прогноз.

Для одной или двух переменных меняюсь, у меня есть функция data_slice() в моем пакете gratia , которая сделает для вас вышеуказанные expand.grid() вещи, так что вам не нужно указывать средние значения другие ковариаты:

preddata <- data_slice(m, 'dewpoint', n = 300)

технически это находит значение в данных, ближайших к срединному значению (для ковариат не меняется). Если ты хочешь средства, то делай

fixdf <- data.frame(windspeed = mn.windspd, temperature = mn.temp)
preddata <- data_slice(m, 'dewpoint', data = fixdf, n = 300)

Если у вас есть взаимодействие, скажем, между dewpoint и windspeed, тогда вам нужно варьировать две переменные. Это довольно легко снова с expand.grid():

mn.temp <- m$cmX['temperature']
preddata <- with(df,
                 expand.grid(dewpoint = seq(min(dewpoint),
                                            max(dewpoint),
                                            length = 100),
                             windspeed = seq(min(windspeed),
                                             max(windspeed),
                                             length = 300),
                             temperature = mn.temp))

Это создаст сетку значений ковариат 100 × 100 для прогнозирования, в то же время поддерживая постоянную температуру.

Для data_slice() вам нужно сделать:

fixdf <- data.frame(temperature = mn.temp)
preddata <- data_slice(m, 'dewpoint', 'windpseed',
                       data = fixdf, n = 300)

И распространяя это на большее число ковариат, которые вы хотите варьировать, также легко следовать этому шаблону с expand.grid(); Мне еще предстоит реализовать более 2 переменных, различающихся по data_slice.

...