模型检查模拟数据(生存模型示例)

杰奎琳·布罗

2016-06-22

第一次分析:参数生存模型

对于我们的第一次分析,我们将使用参数威布尔生存模型。

我们将从模型代码开始wei_bg.stan.在这内github repo.随同Peltola等,2014年漂亮的论文,描述了贝叶斯评估的贝叶斯方法。

该模型假设事件发生的时间X服从威布尔分布。

Stan参数化此概率密度函数为:

\ [f (x | \α\σ)= \压裂{\α}{\σ}\离开(\压裂{x}{\σ}\右)^ ^ {\ alpha -} e {- (x / \σ)^{\α}}\]

在此分析的上下文中,我们将定义两个参数:

如果我们有协调因子并希望估计比例危险模型,我们将取代μ用协变量的线性组合。然而,在这种情况下,我们感兴趣的是恢复我们的NULL模型的特性,所以我们处理μ作为常数截距。

模型的Stan代码

我们将使用的stan代码在本文中提供生物奥斯坦套餐

它可以通过system.file.,如:

如果 (!要求(biostan)) devtools::install_github.'jburos / biostan'图书馆(biostan)stan_file < -system.file.“斯坦”“weibull_survival_null_model.stan”包=“biostan”

以下是该文件的内容:

biostan::print_stan_file.(stan_file)
## / *变量命名:## OB =观察## CEN =(右)被审查## n =样本数## tau = scale参数## * / ##数据{## INT  nobs;## int  ncen;## Vector [nobs] yobs;## Vector [ncen] Ycen;##} ## ##变换数据{##真实 tau_mu;##真实 tau_al;## ## tau_mu < -  10.0;## tau_al < -  10.0;##} ## ##参数{## Real alpha_raw;##真穆; ## } ## ## transformed parameters { ## real alpha; ## alpha <- exp(tau_al * alpha_raw); ## } ## ## model { ## yobs ~ weibull(alpha, exp(-(mu)/alpha)); ## increment_log_prob(weibull_ccdf_log(ycen, alpha, exp(-(mu)/alpha))); ## ## alpha_raw ~ normal(0.0, 1.0); ## mu ~ normal(0.0, tau_mu); ## } ##

详细的模型

在使用这个模型进行分析之前,我们想首先详细地审查模型代码并针对一些模拟数据测试它。

这将确保(a)我们理解模型良好,(b)模型可以从模拟数据中恢复估计。

(如您所见,模拟数据进程的几个部分也可以重新用于后退预测检查。因此,我们将在以后的步骤中保存要重复使用的过程的组件。)

如果您在R控制台,您可以在编辑器中打开STAN文件,如下所示:

如果(交互的())file.edit(stan_file)

查看数据块

让我们先查看数据块。

这将告诉我们模型输入数据的结构和格式。

print_stan_file.(stan_file节=“数据”
##数据{## int  nobs;## int  ncen;## Vector [nobs] yobs;## Vector [ncen] Ycen;##}

被审查和观察的数据点作为单独的输入向量提供。

观察到的数据点

  • 脑袋:观察到的数据点数
  • 社会毒瘤:观察事件的时间

审查数据点

  • 商品:审查的数据点数
  • ycen:被审查的事件

回想一下,这是一个NULL模型(没有协变量值),所以不需要观察到的协变量的数量和值。

查看模型块

在线性预测器中,stan代码包含一个隐式常数项μ

print_stan_file.(stan_file节=“模型”
##模型{## yobs ~ weibull(alpha, exp(-(mu)/alpha)));## increment_log_prob(weibull_ccdf_log(ycen, alpha, exp(-(mu)/alpha)));## ## alpha_raw ~ normal(0.0, 1.0);## mu ~ normal(0.0, tau_mu);##}

观察CCDF(互补累​​积分布函数)如何使用审查观测的日志概率来计算。

在这种情况下,ccdf代表什么?

模型如何处理截尾过程?

检查参数块

我们的斯坦代码还包含了一个Reparameterizationα术语,在转换参数堵塞。

观察:

print_stan_file.(stan_file节=的转换参数
##变换参数{##真正的alpha;## alpha < -  exp(tau_al * alpha_raw);##}

(回想一下,tau_al.常数缩放项是否设置为10alpha_raw是具有正常(0,1)的先前分配的参数)。

这种重新参数化实现了两个目的:

  1. 指某东西的用途tau_al * alpha_raw是一个例子明确参数化
    • 这是数学相当于定义一个(未转换的)参数α与之前的正常(0,10)
    • 然而,此参数化将产生一个参数(alpha_raw),其规模与我们模型中的其他参数相似。这exp ()转变使这两个尺度之间的差异更加戏剧性。
    • 通常,在类似规模上具有所有参数使采样更有效。
  2. exp ()转换此参数允许我们先前日志α
    • 我们想先进日志α因为进入指数的可能性。

这似乎是很多体操都在做。

然而,它对我们的建模效率有实际意义。

观察到一个值alpha_raw(例如0.2),转换产生:

alpha_raw < -0.2tau_al < -10log_alpha < -alpha_raw *tau_alα< -经验值(log_alpha)打印(α)
## [1] 7.389056

这似乎愚蠢。

然而

考虑通过一系列值的Alpha分布alpha_raw从我们那里取样正常(0,1)事先的:

alpha_raw < -rnorm10000.1)tau_al < -10log_alpha < -alpha_raw *tau_alα< -经验值(log_alpha)GGPLOT.data.framealpha =α,alpha_raw =alpha_raw),aesX =alpha))+geom_density() +scale_x_log10.标签=科学)

注意搞定怎么α取值范围为1e-10到1e+10。我们必须大幅度地截断它来考虑在原来的尺度上画它。

采样此参数空间可能需要在此分布过程中不同的一步大小和不同的调整参数值。

alpha_raw相比之下,缩放是一个很多比较友好。

GGPLOT.data.framealpha =α,alpha_raw =alpha_raw),aesX =α,y =alpha_raw))+geom_denys2d.() +scale_x_log10.标签=科学)

该分布以0为中心,在其值范围内具有更一致的行为。

这里需要注意的是,虽然非中心参数化在数学上等同于标准参数化,但它(在某些方面)是一个不同的模型。您可能会得到每个结果。

包就像rstanarm它为默认情况下使用非居中的参数化提供易于包装的包装。

更多关于非中心参数化的信息:

  1. 讨论STAN-DEV列表
  2. Gelman,2004.参数化和贝叶斯建模

在模拟数据上测试模型

现在我们已经审查了模型代码,我们已准备好根据此模型模拟数据。

我们可以使用R或STAN模拟数据。我们将首先模拟R.中的数据。

模拟r中的数据

像我们的stan模型代码一样,这种功能适应了的例子。R代码来自stan-survival-shrinkage github回购

在这里,我们编写了一个需要我们两个参数的函数(αμ)作为输入,以及期望的观测和删失观测数。它返回模拟事件时间的数据帧。

sim_data < -功能(alpha,mu,nobs,ncen){devalided_data < -data.frameos_status =.rep_len'死者',nobs),os_months =.rweibulln =脑袋,α,经验值(-(μ)/α)),stringsasfactors =F) censored_data <-data.frameos_status =.rep_len“生活”,ncen),os_months =.(ncen)*rweibull(NCEN,Alpha,经验值(-(μ)/α)),stringsasfactors =F )返回(observed_data % > %bind_rows.(CISCORED_DATA)))}

关于此功能的一些评论:

  1. 注意一下审查过程runif()。通常,我们的Stan模型不知道截尾过程,除了假设截尾是无信息的。
  2. 我们还故意写入此功能以镜像膀胱癌数据的结构。

这将使以后更容易重用该函数。

模拟任意输入值的数据

我们可以使用它来模拟数据集进行假设参数值αμ

test_alpha < -0.8test_mu < --3.##来自TCGA BLCA Data Test_nobs的示例大小< -179.test_ncen​​ < -230##测试这些输入的alpha和mu模拟数据<-的任意值sim_dataalpha =test_alpha,穆=test_mu,nobs =test_nobs,ncen =test_ncen)(simulated_data)
## Source: local data frame [6 x 2] ## ## os_status os_months ##   ## 1 DECEASED 11.441454 ## 2 DECEASED 17.362348 ## 3 DECEASED 1.439942 ## 4 DECEASED 23.616051 ## 5 DECEASED 37.779830 ## 6 DECEASED 9.369964

得到如下生存曲线:

##从模拟数据Simulated_data < -   -simulated_data%>%dplyr::变异os_deceased =os_status = ='死者'autoplot.(生存::苏克福特Surv.(os_months,os_deced)〜1data =simulated_data),conf.int =f)+ggtitle.'模拟km curve'

适合斯坦中的模拟数据

现在我们已经模拟了数据,我们已经准备好在Stan中拟合模型了。

如果我们正确地编写了我们的STAN代码和模拟数据流程,我们的后续间隔αμ应包含用于模拟我们数据集的值(0.8和-3)。

为Stan准备数据

Stan将数据输入作为一个列表。列表的内容应与数据块在stan代码中。

例如,查看数据块-

print_stan_file.(stan_file节=“数据”
##数据{## int  nobs;## int  ncen;## Vector [nobs] yobs;## Vector [ncen] Ycen;##}

我们给Stan的输入列表应该分别包含观察和审查数据的尺寸和值。

观察到_data < -simulated_data%>%dplyr::筛选(os_status ==.'死者')被审查_data < -simulated_data%>%dplyr::筛选(os_status!='死者')stan_data < -列表nobs =(观察到_data),ncen =(被审查的_data),yobs =观察到的_data $ os_months,ycen =c ensered_data $ os_months)rm(censored_data)rm(观察到_data)str(stan_data)
## # $ Nobs: int 179 ## $ nen: int 230 ## $ yobs: num[1:179] 11.44 17.36 1.44 23.62 37.78…## $ ycen: num[1:30] 3.28 71.29 134.28 11.25 28.51…

(在函数中包装此预备数据流程gen_stan_data.为以后)

gen_stan_data < -函数(数据){devalided_data < -数据%>%dplyr::筛选(os_status ==.'死者')被审查_data < -数据%>%dplyr::筛选(os_status!='死者')stan_data < -列表nobs =(观察到_data),ncen =(被审查的_data),yobs =观察到的_data $ os_months,ycen =CISCORED_DATA $ OS_MONTHS)}

用斯坦测试模拟值

我们叫斯坦

Recover_simulated < -rstan ::斯坦(stan_filedata =stan_data,链=4.iter =1000种子=1328025050打印(recover_simulated)
## Stan模型的推理:weibull_surviv_null_model。## 4链,每个iter=1000;热身= 500;瘦= 1;每个链的热身后抽牌量=500,总抽牌量=2000## ## mean se_mean sd 2.5% ## alpha_raw -2.000000e-02 1.000000e -01 1.400000e-01 -2.000000e-02 ## mu -3.120000e+00 9.1000e-01 1.290000e+00 4.230000e+00 9.560000e+00 7.90000e -01 ## lp__ -2.581429e+62 3.1608e+62 4.472291e+62 -1.034708e+63 ## 25% 50% 75% 97.5% n_eff r# # alpha_raw -2.000000e-02 -0.01 0.08 0.31 2 33.85## mu -3.950000e+00 -3.77 -2.71 -0.89 2 7.90 ## alpha 8.500000e-01 0.89 6.50 22.95 2 262.44 ## lp__ -2.574767e+62 -963.74 -963.07 -962.72 2 1235.65 ## ## Samples were drawn using NUTS(diag_e) at Wed Jun 22 22:22:21 2016. ## 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).

这张照片有什么问题?

(A:收敛性差)(A:在一些链中,我们看到很多数值问题)

设置初始值

这个步骤通常是可选的,但对于某些模型可能是必需的。

在这种情况下,设置初始值可能很有用。回想一下我们转换参数的投影范围α

默认情况下,STAN为-2和2之间的不受约束量表中的每个参数选择一个随机初始值。此随机初始化是不受约束的支持对于每个参数。这保证了初始值与约束范围一致。

然而,当我们传递初始值时,这些都在制约规模。看看斯坦手册有关应用于约束变量的转换的更多细节。

gen_inits函数

让我们再次查看这个模型的参数块。

print_stan_file.(stan_file节='参数'
##参数{## Real Alpha_raw;##真穆;##}

我们有两个应该设置初始值的参数。

让我们尝试修改初始范围alpha_raw利用比默认值更小的范围。

gen_inits < -功能() {列表alpha_raw =0.01*rnorm1),穆=rnorm1))))}

我们将其封装在一个函数中,以便每个链将有不同的初始值集。

带有初始值的Stan代码

让我们尝试使用我们的初始值函数重新拟合我们的STAN模型。

recover_simulated2 < -rstan ::斯坦(stan_filedata =stan_data,链=4.iter =1000init =gen_inits)打印(Recover_Simulated2)
## Stan模型的推理:weibull_surviv_null_model。## 4链,每个iter=1000;热身= 500;瘦= 1;每个链的热身后抽牌量=500,总抽牌量=2000# # # #意味着se_mean sd # # alpha_raw 2.5% 25% 50% 75% 97.5% -0.01 0.00 0.01 -0.02 -0.02 - -0.01 -0.01 - 0.00 # # -3.87 0.01 0.21 -4.29 -4.01 -3.86 -3.74 -3.45μα# # 0.88 0.00 0.05 - 0.78 0.84 - 0.87 0.91 - 0.97 # # lp__ -963.69 0.05 0.98 - -966.23 -964.13 - -963.37 -962.96 - -962.70 # # n_eff小红帽# # # 1.02 # alpha_raw 257亩258 1.02 1.02α# # 264 # # lp__ 4481。0.0.## ## Samples were drawn using NUTS(diag_e) at Wed Jun 22 22:22:26 2016. ## 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).

现在我们看到更少的数值问题,更好的R帽子值。

检查收敛

通常,我将进一步挖掘该模型以检查收敛,因为单独的R帽是不足以确定会聚。

但在这种情况下,我被参数值的后验估计的总结分散了注意力。

我们是否恢复了参数值?

我们用于模拟我们的数据的值不会落入我们模型中的95%可信的间隔。

我会在收敛的情况下快速检查,看看这是否可以通过缺乏融合来解释。

回顾traceplots

回顾档案普罗特LP__(对数后验),可反映模型整体拟合:

rstan ::磨写(Recover_simulated2,“lp__”

并且,审查关键参数的磨写:

rstan ::磨写(Recover_simulated2,C'α'“亩”),ncol =.1

这两种看起来模糊毛毛虫样。

发射闪亮斯坦

然后你也可以推出Shinystan.要查看这是否有助于诊断任何收敛问题。

如果(交互的())Shinystan ::发射_shinystan.(Recover_Simulated2)

但是,总的来说,缺乏收敛性似乎不能解释估计参数值和用来模拟我们数据的参数值之间的差异。

思考审查

如果我们要将我们的输入数据限制为观察到的事件,该怎么办?

recover_simulated_obs < -rstan ::斯坦(stan_filedata =gen_stan_data.(simulated_data%>%dplyr::筛选(os_status ==.'死者')),链=4.iter =1000init =gen_inits)打印(recover_simulated_obs)
## Stan模型的推理:weibull_surviv_null_model。## 4链,每个iter=1000;热身= 500;瘦= 1;每个链的热身后抽牌量=500,总抽牌量=2000## ##均值SE_MEN SD 2.5%25%50%75%97.5%## alpha_raw -03 0.00 0.01 -0.03 -0.02 -0.01 ## mu -2.93 0.01 0.21 -3.35 -3.07 -2.94 -2.79  -2。54 ## alpha 0.78 0.00 0.04 0.69 0.75 0.78 0.81 0.87 ## lp__ -870.97 0.05 0.98 -873.66 -871.38 -870.69 -870.26 -870.00 ## n_eff Rhat ## alpha_raw 322 1.03 ## mu 301 1.03 ## alpha 318 1.03 ## lp__ 417 1.01 ## ## Samples were drawn using NUTS(diag_e) at Wed Jun 22 22:22:33 2016. ## 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).

而且,审查了审查的意见?

recover_simulated_cen < -rstan ::斯坦(stan_filedata =gen_stan_data.(simulated_data%>%dplyr::筛选(os_status!='死者')),链=4.iter =1000init =gen_inits)打印(recover_simulated_cen)
## Stan模型的推理:weibull_surviv_null_model。## 4链,每个iter=1000;热身= 500;瘦= 1;每个链的热身后抽牌量=500,总抽牌量=2000## ##表示SE_Mean SD 2.5%25%50%75%97.5%N_EFF rhat ## alpha_raw -0.19 0.01 0.14 -0.42 -0.31 -0.20 -0.08 0.08 250 1.03 0.43 5.43 -27.16 -15.80 -11.45-8.73 -5.81 161 1.02 ## alpha 0.39 0.04 0.02 0.02 0.05 0.10 0.46 2.23 251 1.02 ## LP__ -1.12 0.07 0.86 -3.72 -1.38 -0.80 -0.56 -0.45 151 1.02 ########################################################################020207 0.86 -3.72 -1.45 151 1.02 ## ##2016年6月22日星期三。##对于每个参数,N_EFF是有效样本大小的粗略衡量标准,##和rhat是拆分链上的潜在规模缩小因子(在##融合,rhat = 1时)。

我们发现(这并不奇怪)我们从审查的观察中得出了非常糟糕的推论- ..我们能够恢复我们的参数估计,当限制仅观察数据点。

这是我们的第一个提示,无法恢复参数估计的无法与数据被审查有关。这只是将错误引入我们的推论吗?

后预测检查

接下来,我们可能会问,在恢复用于模拟数据的参数时出现的错误是否具有实质性。如果我们对生物标志物的推断是持续的,也许我们在估计基线危险参数时可能有点偏差?

为此,我们将模拟来自参数后绘制的数据。这些被称为后预测值。它们的分布是后预测分布

从Stanfit对象中提取参数

我们使用rstan :: extract()函数从stanfit对象中提取参数。

例如。提取αμ

pp_alpha < -rstan ::提炼(Recover_simulated2,'α')αpp_mu < -美元rstan ::提炼(Recover_simulated2,“亩”)$ MU.

每一个都是一个1xD向量的值,其中D =后验(热身后)的画数。

在本例中,我们有2000个:4个链* 1000次迭代/ 2

模拟每次后拉的数据

我们可以用哈德利的Purrr :: Map2.为每对模拟数据μ*α价值观。

pp_newdata < -purrr::map2.x =pp_alpha,.Y =pp_mu,.f =sim_dataalpha =。X,穆=。那,nobs =test_nobs,ncen =test_ncen))

我们现在有一个d datasets列表,每个数据集包含根据该绘制的参数值的模拟μα

让我们在后面的绘图中绘制事件发生的时间,并将其与用于拟合模型的测试数据集进行比较。

GGPLOT.(pp_newdata%>%dplyr::bind_rows.()%>%dplyr::变异类型='后部预测值'%>%bind_rows.(simulated_data%>%dplyr::变异类型=实际数据的)),aesX =os_months,组=os_status,颜色=os_status,填补=os_status))+geom_densityalpha =0.5) +Facet_Wrap.(~类型,ncol =.1

非常相似。

总结后预测绘制

接下来,我们可能会询问生存曲线的后验估计。我们如何估计这一点?

一种方法(可能有几个)是:1。从后部的每个抽取计算每个观察到的时间点的累积存活率。将累积存活率汇总到离散单位3.总结每个间隔的累积生存率后射。

这就是我们将在这里使用的方法。

##每个后部绘制的累积存活率Pp_survdata < -pp_newdata%>%purrr::地图(~dplyr::变异(。,os_deceased =os_status = ='死者'))%>%purrr::地图(~生存::苏克福特Surv.(os_months,os_deced)〜1data =。))%>%purrr::地图(fortify) ##总结每个单位时间(月)的生存,总结在95%置信区间pp_survdata_agg <-pp_survdata % > %purrr::地图(~dplyr::变异(。,time_group =地板上(时间)))%>%dplyr::bind_rows.()%>%dplyr::通过...分组(time_group) % > %dplyr::总结surv_mean =吝啬的(surv),surv_p50 =中位数(surv),surv_lower =斯蒂利韦(SURV,聚合氯化铝=0.025),surv_upper =斯蒂利韦(SURV,聚合氯化铝=0.975))%>%dplyr::取消组()

最后,我们覆盖了从我们原始的测试数据集中的生存曲线的后预测模拟。

测试数据测试数据test_data_kmcurve < -巩固(生存::苏克福特Surv.(os_months,os_deced)〜1data =simulated_data%>%dplyr::变异os_deceased =os_status = ='死者')))%>%dplyr::变异较低=surv,上=surv)GGPLOT.(pp_survdata_agg%>%dplyr::变异类型='后部预测值'%>%dplyr::改名surv =surv_p50,较低=SURV_LOWER,上=surv_upper,时间=time_group)%>%bind_rows.(test_data_kmcurve % > %dplyr::变异类型=实际数据的)),aesX =时间,组=类型,linetype =.类型))+geom_lineaesy =surv,颜色=类型))+geom_ribbon.aesymin =降低,ymax =上),alpha =0.2) +XLIM.C0.200))

在这里,我们看到生存曲线的巨大差异,将我们的原始模拟数据与我们的后后预测分布进行比较。

保存为函数

如前所述,我们将希望在功能中包装它,以便在将来的步骤中重复使用,例如,它可以重复使用。当我们使用我们的TCGA数据时。

pp_predict_surv < -功能(pp_alpha,pp_mu,nobs,ncen,级别=0.9情节=F,data =sim_data_fun =sim_data){pp_newdata < -purrr::map2.x =pp_alpha,.Y =pp_mu,.f =sim_data_fun.alpha =。X,穆=。那,nobs =nobs,ncen =nen)) pp_survdata <-pp_newdata%>%purrr::地图(~dplyr::变异(。,os_deceased =os_status = ='死者'))%>%purrr::地图(~生存::苏克福特Surv.(os_months,os_deced)〜1data =。))%>%purrr::地图(fortify)##计算定量级别LeverLuply_p < -0.+((1-等级)/2) upper_p < -1-((1-等级)/2)pp_survdata_agg < -pp_survdata % > %purrr::地图(~dplyr::变异(。,time_group =地板上(时间)))%>%dplyr::bind_rows.()%>%dplyr::通过...分组(time_group) % > %dplyr::总结surv_mean =吝啬的(surv),surv_p50 =中位数(surv),surv_lower =斯蒂利韦(SURV,聚合氯化铝=下_P),surv_upper =斯蒂利韦(SURV,聚合氯化铝=upper_p)) % > %dplyr::取消组() if (plot ==错误的){返回(pp_survdata_agg)} ggplot_data < -pp_survdata_agg % > %dplyr::变异类型='后部预测值'%>%dplyr::改名surv =surv_p50,较低=SURV_LOWER,上=surv_upper,时间=time_group)如果(!一片空白(数据))ggplot_data < -ggplot_data % > %bind_rows.巩固(生存::苏克福特Surv.(os_months,os_deced)〜1data =数据%>%dplyr::变异os_deceased =os_status = ='死者')))%>%dplyr::变异较低=surv,上=surv,类型=实际数据的))pl < -GGPLOT.(ggplot_dataaesX =时间,组=类型,linetype =.类型))+geom_lineaesy =surv,颜色=类型))+geom_ribbon.aesymin =降低,ymax =上),alpha =0.2)PL}

PP检查观察到的事件仅限模型

当我们将模型限制在只观察到的事件时,我们的实际数据与我们的后验预测值有多好?

pp_alpha_obs < -提炼(recover_simuld_obs,'α')$ alpha pp_mu_obs < -提炼(recover_simuld_obs,“亩”)$ mu pl < -pp_predict_survpp_alpha =pp_alpha_obs,pp_mu =pp_mu_obs,nobs =test_nobs,ncen =0.情节=T,data =simulated_data%>%dplyr::筛选(os_status ==.'死者'))pl +ggtitle.'PP检查模拟数据\ n(模型适合使用观察到的事件)') +XLIM.NA200

这是后验预测检查如何有用的一个例子。

此时,我们知道数据模拟过程、模型或两者都存在问题。

我怀疑这与审查有关。runif())数据仿真中的过程。

检查数据仿真

让我们尝试备用数据模拟过程,其中审查与生存时间无关。

alt_sim_data < -function(alpha, mu, Nobs, nen) {data <-data.framesurv_months =rweibulln =脑袋+商品,α,经验值(-(μ)/α)),CINSOR_MONTHS =.雷克斯n =脑袋+ncen,率=1/One hundred.),stringsasfactors =F) % > %dplyr::变异os_status =.如果别的(surv_months <.CINSOR_MONTHS,'死者'“生活”),os_months =.如果别的(surv_months <.CINSOR_MONTHS,SURV_MONTHS,CENSOR_MONTHS))返回(数据) }

接下来,我们根据这个函数模拟新的数据,并尝试使用Stan恢复参数估计。

alt_simulated_data < -alt_sim_data.alpha =test_alpha,穆=test_mu,ncen =test_ncen​​,nobs =test_nobs)autoplot.(生存::苏克福特Surv.(os_months,一世(os_status ==.'死者')) ~1data =alt_simulated_data)))

有多少经过审查的观察?

表格(alt_simulated_data $ os_status)
## ##已故生活## 290 119

我们可以通过模型恢复参数估计吗?

recover_alt_simulated < -rstan ::斯坦文件=stan_file,data =gen_stan_data.(alt_simulated_data),链=4.iter =1000init =gen_inits)打印(recover_alt_simulated)
## Stan模型的推理:weibull_surviv_null_model。## 4链,每个iter=1000;热身= 500;瘦= 1;每个链的热身后抽牌量=500,总抽牌量=2000## ##表示SE_Mean SD 2.5%25%50%75%## alpha_raw -0.02 0.00 0.00 0.00 0.0 0.03 -0.02 -0.02 ## mu -2.98 0.01 0.14 -3.25 -3.08 -2.98 -2.88 ## alpha 0.78 0.000.03 0.71 0.76 0.78 0.81 ## LP__ -1384.96 0.04 0.94 -1387.67 -1385.31 -1384.66 -1384.31 ## 97.5%n_eff rhat ## alpha_raw -0.02 403 1.01 ## mu -2.69 385 1.01 ## Alpha 0.85 400 1.01 ## LP__  -13.84.06 544 1.01 ## ## Samples were drawn using NUTS(diag_e) at Wed Jun 22 22:23:24 2016. ## 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).

对该分析进行后验预测检查

pp_alpha < -rstan ::提炼(recover_alt_simulated'α')αpp_mu < -美元rstan ::提炼(recover_alt_simulated“亩”)$ mu pl < -pp_predict_survpp_alpha =pp_alpha,pp_mu =pp_mu,sim_data_fun =alt_sim_data,nobs =test_nobs,ncen =test_ncen​​,情节=T,data =Alt_simulated_data) pl +ggtitle.'实际和后部预测数据的KM曲线\ n修改模拟数据函数后'

最后的想法

总而言之,我们试图检查我们的模型代码针对模拟数据,但不小心模拟了我们的数据,具有信息丰富的审查过程。

显而易见的是,我们的模型无法恢复用于模拟数据的参数值,这首先令人不安。但是,观察到更有用的是,在我们的数据上进行后续预测检查的标准工作流程也表明了一些东西。

有这些数据不是已经模拟了,而且它们来自(例如)临床研究,我们不会知道先天的审查过程是信息性的。我们也没有知道的后估计μα不正确。然而,什么是令人鼓舞的是后验预测检查确实表明我们有问题。很明显,后部预测分配与我们的实际数据不相符。

这里,由于我们正在使用模拟数据,我们能够通过修改模拟数据进程来解决关注。在实际分析的上下文中,修改数据不是可能性(!),因此必须调整模型以占审查过程。