Haskell 概率规划语言的自由单子建模观察

Haskell 概率规划语言的自由单子建模观察,haskell,monads,dsl,free-monad,Haskell,Monads,Dsl,Free Monad,我试图实现一个DST的概率编程灵感来自 DST的免费monad(包括bernoulli和beta发行版)可能如下所示: 数据模型= 伯努利双精度(布尔->r) |BetaF双双双(双->r) 派生(函子) 类型模型=自由模型F 伯努利::双->模型布尔 伯努利p=liftF(伯努利p-id) beta::Double->Double->Model Double beta a b=liftF(BetaF a b id) 我想扩展它以支持对分布的观察。即:强制一个特定的返回值 第一次尝试是扩展函子

我试图实现一个DST的概率编程灵感来自

DST的免费monad(包括bernoulli和beta发行版)可能如下所示:

数据模型=
伯努利双精度(布尔->r)
|BetaF双双双(双->r)
派生(函子)
类型模型=自由模型F
伯努利::双->模型布尔
伯努利p=liftF(伯努利p-id)
beta::Double->Double->Model Double
beta a b=liftF(BetaF a b id)
我想扩展它以支持对分布的观察。即:强制一个特定的返回值

第一次尝试是扩展函子:

data ModelF r =
    BernoulliF Double (Bool -> r)
  | BetaF Double Double (Double -> r)
  | ObsF (ModelF r) r
  deriving (Functor)
然而,这是有问题的,因为它允许递归嵌套
ObsF

一种解决方案是将自由单体提升到另一个表示观察值的自由单体中:

data ObsModelF r =
    PureF (Model r)
  | ObsF (Model r) r
  deriving (Functor)

observe :: Model r -> r -> Free ObsModelF r
observe model o = liftF (ObsF model o)
不过,我所追求的语法是:

let dist = do
      p <- beta 1 1
      observe (bernoulli p) True

我包括了一个非常简单的解释器(
toSampler
)。目前它完全忽略了分布,只是将观测值平面化。请注意,这不是在分布上调节时的预期行为。提供它只是为了显示解释器将如何遍历自由结构。

我熟悉其他语言/DSL中类似的内容。我不确定我脑子里想的东西是否正是你想要的,但我会给你一个大概的想法。也许你会发现它很有用

我熟悉的
observe
有一种类似于
分布a->a->Model()
的类型,它被解释为将当前路径通过模型的概率乘以分布下观测的概率(/密度)。这个
观测
采用
分布
,而不是
模型
,因为我们需要一种方法来计算观测的概率(/密度)

一旦有了
分布
类型,还可以用单个操作替换每个分布操作,以引入不确定性。这将以
分布
作为参数

我有一个Haskell DSL,基本上是这样工作的。唯一的区别是,
observe
是一个更简单的操作,它可以任意修改当前路径的日志概率

顺便说一句,这种方法完全脱离了语言。

这里有一个建议

data ModelF r =
    BernoulliF Double (Bool -> r)
  | BetaF Double Double (Double -> r)
  | ObsFail
  deriving (Functor)
那你就可以了

let dist = do
      p <- beta 1 1
      b <- bernoulli p
      if (b==True)
          then return ()
          else ObsFail
let dist=do

p我不确定您希望从
ObsModelF
类型中得到什么语义。你能给我写个口译员澄清一下吗?另外,使用
PureF
或类似
lift
的函数包装
beta 1 1
有什么问题?我想
观察一下
的任意分布。如果我使用
Pure
(伯努利和贝塔)解除所有发行版,我将不得不再次使用
ObsF
解除伯努利的发行版。一个simpel任务似乎需要很多操作。我想要实现的是通过“标记”观察到的返回值来修复
modelfr
返回值。我可以试着在问题正文中详细阐述。通过阅读博文和其他一些材料,我对观察的含义有了一些了解,但我目前无法与你的类型相一致,因此我要求请一名翻译来查看。此外,对语言用户来说,通常可以很容易地隐藏包装/展开,但如果先有一个工作实现,则更容易找到清理API的适当方法。@李耀霞我已经用包括解释器的第三次尝试更新了答案。如果您能看一看并帮助我了解问题所在,我将不胜感激。您可以使用
ObsF!(ModelF r)r
如果您想确保它不会无限期嵌套。看起来是一个非常好的端口–我一定会仔细看看。如果还没有,你也应该去看看。似乎有一些相似之处。看起来他们也开始添加单站点MH,这不是原始文件的一部分。我的解释器最终会将其映射到单个站点MH,因此观察应该修复给定分布的
logPdf
sample
。我很难理解如何将它建模为一个免费的monad–你会将免费的monad堆叠起来吗?
let dist = do
      p <- beta 1 1
      b <- bernoulli p
      if (b==True)
          then return ()
          else ObsFail
observe dist r = do
    r' <- dist
    if r == r'
        then return ()
        else ObsFail