Julia Gen:如何在高阶生成函数中组合多个生成函数轨迹?

Julia Gen:如何在高阶生成函数中组合多个生成函数轨迹?,julia,inference,generative,probabilistic-programming,generative-programming,Julia,Inference,Generative,Probabilistic Programming,Generative Programming,我将在上浏览“Gen建模入门”笔记本 第5节(调用其他生成函数)要求“构造一个数据集,对于该数据集,直线模型或正弦波模型是否最佳尚不明确” 我很难理解如何使用组件函数的跟踪(和返回)来创建一个有意义的高阶跟踪,我可以使用它 对我来说,最直接的“模糊”模型是line(xs)。+sine(xs)。因此,我将模拟Gen.simulateedline和sine以获得轨迹并将它们相加,如下所示: @gen函数组合(xs::Vector{Float64}) my_sin=模拟(正弦模型_2,(xs,) my

我将在上浏览“Gen建模入门”笔记本

第5节(调用其他生成函数)要求“构造一个数据集,对于该数据集,直线模型或正弦波模型是否最佳尚不明确”

我很难理解如何使用组件函数的跟踪(和返回)来创建一个有意义的高阶跟踪,我可以使用它

对我来说,最直接的“模糊”模型是
line(xs)。+sine(xs)
。因此,我将模拟
Gen.simulate
ed
line
sine
以获得轨迹并将它们相加,如下所示:

@gen函数组合(xs::Vector{Float64})
my_sin=模拟(正弦模型_2,(xs,)
my_lin=模拟(直线模型_2,(xs,))
如果@trace(伯努利(0.5),:是_线)
@跟踪(正常(获取选项(my_lin)[:slope],0.01),:slope)
@跟踪(正常(获取选项(my_lin)[:intercept],0.01),:intercept)
@跟踪(正常(获取选项(my_lin)[:noise],0.01),:noise)
其他的
@跟踪(正常(获取选项(my_sin)[:phase],0.01),:phase)
@跟踪(正常(获取选项(my_sin)[:period],0.01),:period)
@记录道(正常(获取选项(my_sin)[:振幅],0.01),:振幅)
@跟踪(正常(获取选项(my_sin)[:noise],0.01),:noise)
终止
combo=[get_choices(my_sin)[(:y,i)]+get_choices(my_lin)[(:y,i)],因为i=1:length(xs)]
用于枚举(组合)中的(i,c)
@轨迹(正常(c,0.1),(:y,i))
终止
终止
这显然是错误的,我知道在Gen中跟踪和prob编程的整个思想中,我遗漏了一些基本的东西

我希望能够从combo中内省sine/line_模型的跟踪,并对跟踪进行元素添加以获得新的跟踪。而且不必随机选择一个接近:intercept,:phase等的数字,这样我可以在以后的跟踪中包含它

顺便说一下,当我这样做的时候:

traces = [Gen.simulate(combo,(xs,)) for _=1:12];
grid(render_combined, traces)
我明白了


请帮忙,谢谢

大家好-感谢您对Gen的兴趣!:)

组合模型跟踪的地址

教程中的组合模型如下所示:

@gen function combined_model(xs::Vector{Float64})
    if @trace(bernoulli(0.5), :is_line)
        @trace(line_model_2(xs))
    else
        @trace(sine_model_2(xs))
    end
end;
其跟踪将具有以下地址:

  • :is_line
    ,存储一个布尔值,指示生成的数据集是否为线性数据集
  • 来自
    line\u model\u 2
    sine\u model\u 2
    的任何地址,具体取决于调用的地址
请注意,
line\u model\u 2
sine\u model\u 2
的跟踪都包含
(:y,i)
对于
1
长度(xs)
之间的每个整数
i
。因此,
combined\u model
的跟踪也将如此:这些是表示最终采样的
y
值的地址,而不管这两个过程中的哪一个生成了它们

构建新数据集

“构建一个线性或正弦波模型是否最佳的数据集不明确”的问题不需要编写一个新的生成函数(使用
@gen
),而是构建一个
xs
列表和一个
ys
列表(简单地说)您认为这可能会使数据集难以消除歧义。然后,您可以将
xs
ys
传递到笔记本中前面定义的
do_推断
函数中,以查看系统对数据集的结论。请注意,
do\u expression
函数构造一个约束选项映射,将每个
(:y,i)
约束为传入数据集中的值
ys[i]
。这是因为
(:y,i)
始终是第i个数据点的名称,而不管
:is_line的值是多少

更新/操作跟踪

你写道:

我希望能够从combo中内省sine/line_模型的跟踪,并对跟踪进行元素添加以获得新的跟踪。而且不必随机选择一个接近:intercept,:phase等的数字,这样我可以在以后的跟踪中包含它

您当然可以调用
simulate
两次,以获得两个跟踪,而不是像
combo这样的生成函数。但是跟踪不能以任意方式进行操作(例如“元素添加”):作为数据结构,跟踪保持某些不变量,例如始终知道生成它们的模型下它们当前值的确切概率,并且始终保持实际可能从模型生成的值

您正在寻找的类似字典的数据结构是一个choicemap。Choicemaps是可变的,可以构建为在任意地址包含任意值。例如,您可以编写:

observations = Gen.choicemap()
for (i, y) in enumerate(ys)
  observations[(:y, i)] = y
end
Choicemaps可用作生成新跟踪的约束条件(使用
Gen.generate
),作为Gen的低级
Gen.update
方法的参数(允许您在重新计算任何相关概率时更新跟踪,如果更新无效则出错),以及在其他几个地方


希望有帮助:)

多亏了亚历克斯·卢的澄清,答案比我想象的要简单得多。以下是我所做的:

xs = [-5:0.1;5;]

ambiguous = [0.3*x+0.2*sin(x)+normal(0,.5) for x in xs];

ambig_trace = do_inference(combined_model,xs, ambiguous, 100)

render_combined(ambig_trace)

制作:

(或者更正弦的东西,如果可以推断的话)

最后:

n_infers = 100
is_sine = 0
for i=1:n_infers
    curr_trace = do_inference(combined_model, xs, ambiguous, 100)
    if !curr_trace[:is_line] is_sine+=1 end
end
println("posterior probability of sine wave model is $(is_sine/n_infers)")

# => posterior probability of sine wave model is 0.52

你可能想在回购协议上问这个问题,因为Gen是全新的,所以这里没有多少人知道。谢谢@chrisrackaukas,我在回购协议->问题上问过,但这不是正确的地方。希望我能在继续学习教程的过程中得到一些指导