如何使用Metropolis-Hastings算法将C或C ++代码合并到我的R代码中以加速MCMC程序

时间:2012-02-10 11:36:30

标签: c r mcmc

我正在寻求有关如何将C或C ++代码合并到我的R代码中以使用Metropolis-Hastings算法加速MCMC程序的建议。我使用MCMC方法来模拟可能性,给定各种协变量,个人将被第三方(法官)分配给社会地位等级中的特定等级:每个法官(大约80个,跨越4个村庄)被要求根据对每个人的社会地位的评估,对一组个人(大约80个,跨越4个村庄)进行排名。因此,对于每个法官,我有一个等级向量,对应于他们对每个人在等级中的位置的判断。

为了对此进行建模,我认为,在分配排名时,评委会根据个人效用的某些潜在衡量标准的相对值来决定, u 。鉴于此,可以假设由给定判断产生的等级向量 r 是未观察到的向量的函数, u ,描述了该实用程序的效用。个人被排名,其中具有 kth 最高值 u 的个人将被分配 kth 等级。我使用感兴趣的协变量将 u 建模为多变量正态分布变量,然后根据模型生成的 u 的分布确定观察到的等级的可能性。

除了估计最多5个协变量的影响外,我还估计了描述法官和项目之间差异的超参数。因此,对于链的每次迭代,我估计多变量法向密度大约为8-10倍。因此,5000次迭代可能需要长达14个小时。显然,我需要运行它超过5000次运行,所以我需要一种方法来大大加快这个过程。鉴于此,我的问题如下:

(i)我是否正确地假设通过在C或C ++中运行一些(如果不是全部)链来获得最佳速度增益?

(ii)假设问题1的答案是肯定的,我该如何处理?例如,有没有办法让我保留所有的R函数,只需在C或C ++中进行循环:即我可以从C调用R函数然后循环吗?

(iii)我想我真正想知道的是如何最好地将C或C ++代码合并到我的程序中。

6 个答案:

答案 0 :(得分:18)

首先确保你的慢R版本是正确的。调试R代码可能比调试C代码更容易。完成了吗?大。您现在可以使用正确的代码进行比较。

接下来,找出花时间的东西。使用Rprof运行代码,看看花了多少时间。我为一些我继承过的代码做了这个,发现它花了90%的时间在t()函数中。这是因为程序员有一个矩阵A,并且在无数个地方做了t(A)。我在开始时做了一个tA = t(A),并用tA替换每个t(A)。大力加速,不费吹灰之力。首先描述您的代码。

现在,你已经找到了瓶颈。是你可以加速R的代码吗?它是一个可以矢量化的循环吗?去做。根据您的黄金标准正确代码检查您的结果。总是。是的,我知道很难比较依赖随机数的算法,所以设置相同的种子并重试。

还不够快?好的,现在也许你需要在C或C ++或Fortran中重写部分(通常是最低级别的部分,以及那些花费大部分时间进行性能分析的部分),或者如果你真的想用它来重写GPU代码。

再次,确实检查代码是否给出了正确的R代码相同的答案。真的检查一下。如果在此阶段您在常规方法中找到任何错误,请将其修复为您认为正确的R代码和最新版本,并重新运行所有测试。建立大量的自动测试。经常运行它们。

阅读有关代码重构的内容。它被称为重构,因为如果你告诉你的老板你正在重写你的代码,他或她会说“你为什么不第一次正确地写它?”。如果你说你正在重构你的代码,他们会说“嗯......很好”。这实际上是发生的。

正如其他人所说,Rcpp是胜利的。

答案 1 :(得分:4)

使用R,C ++和Rcpp的完整示例是provided by this blog post,其灵感来自this post on Darren Wilkinson's blog(他有更多的后续行动)。该示例也包含在目录RcppGibbs中的最新版Rcpp中,应该可以帮助您。

答案 2 :(得分:3)

我有一篇博文,正好讨论了这个话题,我建议你看一下:

http://darrenjw.wordpress.com/2011/07/31/faster-gibbs-sampling-mcmc-from-within-r/

(这篇文章比Dirk所说的我的帖子更有意义。)

答案 3 :(得分:2)

我认为目前集成C或C ++的最佳方法是Dirk Eddelbuettel的Rcpp软件包。您可以在his website找到大量信息。谷歌的谈话available through youtube可能很有趣。

答案 4 :(得分:2)

查看这个项目: https://github.com/armstrtw/rcppbugs

另外,这里是R / Fin 2012演讲的链接: https://github.com/downloads/armstrtw/rcppbugs/rcppbugs.pdf

答案 5 :(得分:0)

我建议对MCMC采样器的每个步骤进行基准测试,并确定瓶颈。如果将每个完整的条件或M-H步骤放入函数中,则可以使用R编译器软件包,这可能会使您获得5%-10%的速度增益。下一步是使用RCPP。

我认为拥有一个通用的RCPP函数真的很不错,它在给定似然函数的情况下使用M-H算法生成一个单一的绘制。

但是,如果您只了解R语言,那么使用RCPP会变得很困难:非标准随机分布(特别是截断的分布)和使用数组。你必须更像是C程序员。

多变量正常实际上是R中的一个大问题.Dmvnorm是非常低效和缓慢的。 Dmnorm更快,但在某些模型中它会比dmvnorm更快地给我NaNs。

也没有采用一组协方差矩阵,因此在许多情况下无法对代码进行矢量化。然而,只要你有一个共同的协方差和手段,你就可以进行矢量化,这就是加快速度的R-ish策略(哪个是你在C中做的事情的对立面)。