2

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

看来我应该使用 state monad 来跟踪随机生成器状态、之前的马尔可夫链状态、卡方值和算法每一步之间的接受计数,然后最后收集所有马尔可夫链状态和最后一次接受数数。这是最好的/惯用的方法吗?如果是这样,程序的布局应该是什么(即提案功能和大都会阶梯功能的类型签名等)。

我见过一些处理随机数的示例程序,其中特定长度的随机数列表是从某种概率单子生成的,然后通过一些简单的函数进行线程化以执行计算。如果可能的话,我真的很想避免这种由内而外的程序形式。

编辑:暂时删除 WIP 代码。

4

1 回答 1

5

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

  • 除非您正在编写单子代码,否则do在纯函数中使用(即constructMuTable, metropolis)是非常不习惯的 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, muVec, sigmaVecin main) 你写过(\x -> f x)。这相当于 just f、 modulo_|_seq

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

  • (!!)尽可能避免使用索引列表。Data.Vector原样使用while V.!is 。_O(1)(!!)O(n)

  • 似乎您可以在State这里使用 monad 来清理您的代码。然而,以目前的命令形式,我很难看到这种转变。

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

于 2014-04-05T19:25:42.597 回答