在Haskell中实现Metropolis算法

时间:2014-04-05 18:35:49

标签: haskell random mcmc

我正在尝试基于Haskell中的Metropolis算法编写MCMC程序,我遇到了从概率分布(生成伪随机数)和构造程序的问题。现在,我很高兴使用带有硬编码种子的生成器,而不是处理处理IO的复杂性。

似乎我应该使用状态monad跟踪随机生成器状态,先前马尔可夫链状态,卡方值和算法的每一步之间的接受计数,然后最终收集所有马尔可夫链状态和最后的接受数。这是最好的/惯用的方式吗?如果是这样,程序的布局应该是什么(即提议函数的类型签名和大都市步骤函数等)。

我已经看到一些处理随机数的示例程序,其中从某种概率monad生成特定长度的随机数列表,然后通过一些简单的函数来执行计算。如果可能的话,我真的想避免这种内部形式的程序。

编辑:暂时删除了WIP代码。

1 个答案:

答案 0 :(得分:5)

以下是关于编写惯用的Haskell的一些反馈。

  • 除非您在编写monadic代码,否则在纯函数中使用do (即。constructMuTablemetropolis)是非常不恰当的Haskell。

    而不是

    foo = do
        let x = ...
            y = ...
            z = ...
        bar x y z
    

    写一下

    foo =
        let x = ...
            y = ...
            z = ...
        in bar x y z
    

    或使用where代替let ... in ...

  • ETA-减少。在zVec中的某些地方(muVecsigmaVecmain),您已撰写(\x -> f x)。这仅相当于f,模_|_seq等。

  • 使用Data.Vector.Unboxed。您有很多V.Vector Double,它们存储了Doubles,并且可能效率低下。对于像Double这样的原始类型,使用未装箱的向量(可能)使用更少的内存来加快代码。

  • 尽可能避免使用(!!)索引列表。使用Data.Vector代替V.!O(1),而(!!)O(n)

  • 您似乎可以在此处使用State monad来清理代码。然而,就目前的势在必行形式而言,我很难看到转型。

也许您可以尝试应用我给出的一些建议并简化一些大型密集函数,然后对您的算法的更高级别反馈将变得更加明显。