Неэффективная выборка простых биномиальных GLM с использованием rstan MCMC - PullRequest
0 голосов
/ 31 августа 2018

Я пытаюсь установить биномиальный GLM, используя пакет rethinking (использует rstan MCMC).

Модель подходит, но выборка неэффективна, и Rhat указывает, что что-то пошло не так. Я не понимаю причину этой проблемы с подгонкой.

Это данные:

d <- read_csv("https://gist.githubusercontent.com/sebastiansauer/a2519de39da49d70c4a9e7a10191cb97/raw/election.csv")
d <- as.data.frame(dummy)

Это модель:

m1_stan <- map2stan( 
 alist(
    afd_votes ~ dbinom(votes_total, p),
    logit(p) <- beta0 + beta1*foreigner_n,
    beta0 ~ dnorm(0, 10),
    beta1 ~ dnorm(0, 10)
  ),
  data = d, 
  WAIC = FALSE,
  iter = 1000)

Диагностика соответствия (Rhat, количество эффективных образцов) показывает, что что-то пошло не так:

      Mean StdDev lower 0.89 upper 0.89 n_eff Rhat
beta0 -3.75      0      -3.75      -3.75     3 2.21
beta1  0.00      0       0.00       0.00    10 1.25

На графике не видна «толстая волосатая гусеница»:

traceplot m0_stan

Вывод stan предложил увеличить два параметра, adapt_delta и max_treedepth, что я и сделал. Это несколько улучшило процесс выборки:

      Mean StdDev lower 0.89 upper 0.89 n_eff Rhat
beta0 18.1   0.09      18.11      18.16    28 1.06
beta1  0.0   0.00       0.00       0.00    28 1.06

Но, как показывает трассировка, все еще что-то не так: traceplot2

Сюжет пар тоже выглядит странно:

pairs plot

Что я еще пробовал:

  • Я центрировал / z-стандартизировал предиктор (выдал эту ошибку: "" Ошибка в сэмплере $ call_sampler (args_list [[i]])): инициализация не удалась. ")
  • Я пробовал обычную модель (но это данные подсчета)
  • Я проверил, что пропусков нет (их нет)
  • Я увеличил количество итераций до 4000, без улучшений
  • Я увеличил sd приоры (для моделей требуется возраст)

Но пока ничего не помогло. В чем может быть причина неэффективного подбора? Что я мог попробовать?

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

 mean(d_short$afd_votes)
[1] 19655.83

Выдержка из данных:

 head(d)
  afd_votes votes_total foreigner_n
1     11647      170396       16100
2      9023      138075       12600
3     11176      130875       11000
4     11578      156268        9299
5     10390      150173       25099
6     11161      130514       13000

информация о сеансе:

sessionInfo()
R version 3.5.0 (2018-04-23)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS High Sierra 10.13.6

Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.5/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] parallel  stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] viridis_0.5.1      viridisLite_0.3.0  sjmisc_2.7.3       pradadata_0.1.3    rethinking_1.59    rstan_2.17.3       StanHeaders_2.17.2 forcats_0.3.0      stringr_1.3.1     
[10] dplyr_0.7.6        purrr_0.2.5        readr_1.1.1        tidyr_0.8.1        tibble_1.4.2       ggplot2_3.0.0      tidyverse_1.2.1   

loaded via a namespace (and not attached):
 [1] httr_1.3.1         jsonlite_1.5       modelr_0.1.2       assertthat_0.2.0   stats4_3.5.0       cellranger_1.1.0   yaml_2.1.19        pillar_1.3.0       backports_1.1.2   
[10] lattice_0.20-35    glue_1.3.0         digest_0.6.15      rvest_0.3.2        snakecase_0.9.1    colorspace_1.3-2   htmltools_0.3.6    plyr_1.8.4         pkgconfig_2.0.1   
[19] broom_0.5.0        haven_1.1.2        bookdown_0.7       mvtnorm_1.0-8      scales_0.5.0       stringdist_0.9.5.1 sjlabelled_1.0.12  withr_2.1.2        RcppTOML_0.1.3    
[28] lazyeval_0.2.1     cli_1.0.0          magrittr_1.5       crayon_1.3.4       readxl_1.1.0       evaluate_0.11      nlme_3.1-137       MASS_7.3-50        xml2_1.2.0        
[37] blogdown_0.8       tools_3.5.0        loo_2.0.0          data.table_1.11.4  hms_0.4.2          matrixStats_0.54.0 munsell_0.5.0      prediction_0.3.6   bindrcpp_0.2.2    
[46] compiler_3.5.0     rlang_0.2.1        grid_3.5.0         rstudioapi_0.7     labeling_0.3       rmarkdown_1.10     gtable_0.2.0       codetools_0.2-15   inline_0.3.15     
[55] curl_3.2           R6_2.2.2           gridExtra_2.3      lubridate_1.7.4    knitr_1.20         bindr_0.1.1        rprojroot_1.3-2    KernSmooth_2.23-15 stringi_1.2.4     
[64] Rcpp_0.12.18       tidyselect_0.2.4   xfun_0.3           coda_0.19-1       

1 Ответ

0 голосов
/ 01 сентября 2018

STAN работает лучше с единичным масштабом, некоррелированными параметрами. Из руководства STAN §28.4 Моделирование и кривизна модели:

В идеале все параметры должны быть запрограммированы так, чтобы они имели единицу измерения. масштаб и так, что задняя корреляция уменьшается; вместе эти свойства означают, что для вращения не требуется вращение или масштабирование оптимальная производительность алгоритмов Стэна. Для гамильтониана Монте-Карло это подразумевает матрицу единичной массы, которая не требует адаптации, поскольку она где алгоритм инициализируется. Риманов гамильтониан монте карло выполняет эти условия на лету на каждом шагу, но такие кондиционирование очень дорого в вычислительном отношении.

В вашем случае beta1 привязан к foreigner_n, который не имеет единичного масштаба и поэтому не сбалансирован по сравнению с beta0. Кроме того, поскольку foreigner_n не центрируется, обе бета-версии меняют местоположение p во время выборки, отсюда и последующая корреляция.

Стандартизация дает более гибкую модель. Преобразование foreigner_n для центрирования и масштабирования в единицах позволяет модели быстро сходиться и дает эффективные размеры выборки. Я также утверждаю, что бета-версии в этой форме более понятны, поскольку beta0 фокусируется только на местоположении p, а beta1 касается только того, как изменение в foreigner_n объясняет изменение в afd_votes/total_votes.

library(readr)
library(rethinking)

d <- read_csv("https://gist.githubusercontent.com/sebastiansauer/a2519de39da49d70c4a9e7a10191cb97/raw/election.csv")
d <- as.data.frame(d)
d$foreigner_z <- scale(d$foreigner_n)

m1 <- alist(
  afd_votes ~ dbinom(votes_total, p),
  logit(p) <- beta0 + beta1*foreigner_z,
  c(beta0, beta1) ~ dnorm(0, 1)
)

m1_stan <- map2stan(m1, data = d, WAIC = FALSE,
                    iter = 10000, chains = 4, cores = 4)

Изучив выборку, мы имеем

> summary(m1_stan)
Inference for Stan model: afd_votes ~ dbinom(votes_total, p). 
4 chains, each with iter=10000; warmup=5000; thin=1;  
post-warmup draws per chain=5000, total post-warmup draws=20000.

              mean se_mean   sd         2.5%          25%          50%          75%        97.5% n_eff Rhat 
beta0        -1.95    0.00 0.00        -1.95        -1.95        -1.95        -1.95        -1.95 16352    1 
beta1        -0.24    0.00 0.00        -0.24        -0.24        -0.24        -0.24        -0.24 13456    1 
dev      861952.93    0.02 1.97    861950.98    861951.50    861952.32    861953.73    861958.26  9348    1 
lp__  -17523871.11    0.01 0.99 -17523873.77 -17523871.51 -17523870.80 -17523870.39 -17523870.13  9348    1

Samples were drawn using NUTS(diag_e) at Sat Sep  1 11:48:55 2018.
For each parameter, n_eff is a crude measure of effective sample size, 
and Rhat is the potential scale reduction factor on split chains (at
convergence, Rhat=1).

И, глядя на график пар, мы видим, что корреляция между бета-версиями уменьшена до 0,15:

enter image description here


Дополнительный анализ

Изначально я интуитивно понимал, что основной проблемой является нецентрированный foreigner_n. В то же время, я был немного смущен, потому что STAN использует HMC / NUTS, что, как мне показалось, должно быть достаточно устойчивым к коррелированным скрытым переменным. Тем не менее, я заметил комментарии в руководстве STAN о практических проблемах с масштабной инвариантностью из-за числовой нестабильности, которые также прокомментировал Майкл Бетанкур в ответе CrossValidated (хотя это довольно старый пост). Итак, я хотел проверить, были ли центрирование или масштабирование наиболее эффективными для улучшения выборки.

Центрирование в одиночку

Центрирование по-прежнему приводит к довольно низкой производительности. Обратите внимание, что эффективный размер выборки составляет буквально одну эффективную выборку на цепь.

library(readr)
library(rethinking)

d <- read_csv("https://gist.githubusercontent.com/sebastiansauer/a2519de39da49d70c4a9e7a10191cb97/raw/election.csv")
d <- as.data.frame(d)
d$foreigner_c <- d$foreigner_n - mean(d$foreigner_n)

m2 <- alist(
  afd_votes ~ dbinom(votes_total, p),
  logit(p) <- beta0 + beta1*foreigner_c,
  c(beta0, beta1) ~ dnorm(0, 1)
)

m2_stan <- map2stan(m2, data = d, WAIC = FALSE,
                    iter = 10000, chains = 4, cores = 4)

что дает

Inference for Stan model: afd_votes ~ dbinom(votes_total, p).
4 chains, each with iter=10000; warmup=5000; thin=1; 
post-warmup draws per chain=5000, total post-warmup draws=20000.

              mean   se_mean          sd         2.5%          25%          50%         75%        97.5% n_eff Rhat
beta0        -0.64       0.4        0.75        -1.95        -1.29        -0.54         0.2         0.42     4 2.34
beta1         0.00       0.0        0.00         0.00         0.00         0.00         0.0         0.00     4 2.35
dev    18311608.99 8859262.1 17270228.21    861951.86   3379501.84  14661443.24  37563992.4  46468786.08     4 1.75
lp__  -26248697.70 4429630.9  8635113.76 -40327285.85 -35874888.93 -24423614.49 -18782644.5 -17523870.54     4 1.75

Samples were drawn using NUTS(diag_e) at Sun Sep  2 18:59:52 2018.
For each parameter, n_eff is a crude measure of effective sample size,
and Rhat is the potential scale reduction factor on split chains (at 
convergence, Rhat=1).

И, похоже, все еще есть проблемный сюжет пар:

enter image description here

Масштабирование в одиночку

Масштабирование значительно улучшает выборку! Даже несмотря на то, что полученные постеры имеют довольно высокую корреляцию, эффективные размеры выборки находятся в приемлемых пределах, хотя и значительно ниже, чем при полной стандартизации.

library(readr)
library(rethinking)

d <- read_csv("https://gist.githubusercontent.com/sebastiansauer/a2519de39da49d70c4a9e7a10191cb97/raw/election.csv")
d <- as.data.frame(d)
d$foreigner_s <- d$foreigner_n / sd(d$foreigner_n)

m3 <- alist(
  afd_votes ~ dbinom(votes_total, p),
  logit(p) <- beta0 + beta1*foreigner_s,
  c(beta0, beta1) ~ dnorm(0, 1)
)

m3_stan <- map2stan(m2, data = d, WAIC = FALSE,
                    iter = 10000, chains = 4, cores = 4)
* * Тысяча шестьдесят-два получая
Inference for Stan model: afd_votes ~ dbinom(votes_total, p).
4 chains, each with iter=10000; warmup=5000; thin=1; 
post-warmup draws per chain=5000, total post-warmup draws=20000.

              mean se_mean   sd         2.5%          25%          50%          75%        97.5% n_eff Rhat
beta0        -1.58    0.00 0.00        -1.58        -1.58        -1.58        -1.58        -1.57  5147    1
beta1        -0.24    0.00 0.00        -0.24        -0.24        -0.24        -0.24        -0.24  5615    1
dev      861952.93    0.03 2.01    861950.98    861951.50    861952.31    861953.69    861958.31  5593    1
lp__  -17523870.45    0.01 1.00 -17523873.15 -17523870.83 -17523870.14 -17523869.74 -17523869.48  5591    1

Samples were drawn using NUTS(diag_e) at Sun Sep  2 19:02:00 2018.
For each parameter, n_eff is a crude measure of effective sample size,
and Rhat is the potential scale reduction factor on split chains (at 
convergence, Rhat=1).

График пар показывает, что все еще существует значительная корреляция:

enter image description here

Следовательно, хотя декоррелирующие переменные действительно улучшают выборку, устранение дисбаланса шкалы является наиболее важным в этой модели.

...