现在我正在使用MonadRandom库。我有一个计算:
metroChain :: (RandomGen g) => Rand g Double
我想多次执行,然后按顺序打印出结果。 或者更确切地说,我想创建一些多计算列表。
要做一次,我会用
main = do
result <- evalRandIO metroChain
print result
或
main = evalRandIO metroChain >>= (\result -> print result)
然而,我在打印任意(n)量的metroChain
结果方面遇到了很多麻烦。
每个结果应该使用最后一个结果末尾给出的RandomGen ...... MonadRandom应该如何工作,对吗?
我已经研究过replicateM
,fmap
和一些变形金刚(虽然我承认我似乎无法理解它们足以掌握它们对我的问题的应用)。
任何人都可以帮助我实现我正在寻找的功能吗?我觉得我错过了很简单的东西。但我对Haskell很新。
答案 0 :(得分:4)
我将进行一次飞跃并假设metroStep
是MCMC Metropolis-Hastings迭代。
你遇到的问题是你希望MH步骤是Markovian,但只是共享RandomGen
状态,这正是replicateM n metroStep
所做的,是不够的。这只能使每个步骤都能够基于独立的随机变量。要进行比较,如果未分享RandomGen
州,则不变性将保证每个metroStep
都相同。
所以你真正需要的是具有RandomGen
状态的东西,以便提供一个伪随机数链,用于生成独立变量样本和一个固定状态,以便在每一步你可以有P(x_i | theta, x_(i-1))
。我们构建一个变换器堆栈来实现这一点 - 我将使用mtl
库和random-fu
,因为我几天前刚刚使用这些库编写了一个MCMC。
metroStep :: (MonadRandom m, MonadState StateSpace m) => m StateSpace
其中StateSpace
是状态空间中的一个点,包括观察到一个未观察到的变量 - 它是似然函数右侧的每个参数。现在,replicateM n metroStep :: (MonadRandom m, MonadState StateSpace m) => m [StateSpace]
是马尔可夫序列StateSpace
点的列表。
然后我们像这样“运行”这个monad堆栈的具体版本
do steps <- (`runRVar` StdRandom) . (`evalStateT` ss0) $ (replicateM n metroStep)
mapM_ print steps
答案 1 :(得分:3)
replicateM
是您在构建随机计算时所需要的。 (除非电话的猜测是正确的。)
foo :: Int -> IO ()
foo n = do
results <- evalRandIO (replicateM n metroStep)
mapM_ print results
然后您希望mapM_
帮助实际打印结果。
这样做你想要的吗?你有什么想让我继续扩展吗?