0

我正在阅读https://github.com/probcomp/gen-quickstart上的“Gen 建模简介”笔记本

第 5 节(调用其他生成函数)要求“构建一个数据集,其中线或正弦波模型是最好的是模棱两可的”

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

对我来说,最直接的“模棱两可”模型是line(xs).+sine(xs). 所以我Gen.simulate编辑linesine获取痕迹并将它们添加在一起,如下所示:

@gen function combo(xs::Vector{Float64})
    my_sin = simulate(sine_model_2,(xs,))
    my_lin = simulate(line_model_2,(xs,))
    if @trace(bernoulli(0.5), :is_line)
        @trace(normal(get_choices(my_lin)[:slope], 0.01), :slope)
        @trace(normal(get_choices(my_lin)[:intercept], 0.01), :intercept)
        @trace(normal(get_choices(my_lin)[:noise], 0.01), :noise)        
    else
        @trace(normal(get_choices(my_sin)[:phase], 0.01), :phase)
        @trace(normal(get_choices(my_sin)[:period], 0.01), :period)
        @trace(normal(get_choices(my_sin)[:amplitude], 0.01), :amplitude)
        @trace(normal(get_choices(my_sin)[:noise], 0.01), :noise)
    end
    combo = [get_choices(my_sin)[(:y, i)] + get_choices(my_lin)[(:y, i)] for i=1:length(xs)]
    for (i, c) in enumerate(combo)
        @trace(normal(c, 0.1), (:y, i))
    end
    end;

这显然是错误的,我知道我在 Gen.

我希望能够从组合中内省 sine/line_model 的迹线,并对迹线进行元素添加以获得新的迹线。并且不必随机选择接近:intercept、:phase 等的数字,因此我可以稍后将其包含在我的跟踪中。

顺便说一句,当我这样做时:

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

我明白了 功能尝试失败

请帮忙谢谢!

4

2 回答 2

1

您好——感谢您对 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_model_2来自或的任何地址sine_model_2,具体取决于调用的地址。

请注意,两者的迹线都包含line_model_2和之间的每个整数sine_model_2的地址。正因为如此,所以 will的跟踪:这些是代表最终采样值的地址,无论两个进程中的哪一个生成它们。(:y, i)i1length(xs)combined_modely

构建新数据集

“构建一个不确定的数据集是线还是正弦波模型是最好的”的问题不需要编写一个新的生成函数(用)@gen,而是构建一个列表xs和一个列表ys) 你认为可能会成为一个难以消除歧义的数据集。然后,您可以将您的xsand传递ysdo_inference之前在笔记本中定义的函数中,以查看系统对您的数据集的结论。请注意,该do_inference函数构造了一个约束选择映射,将每个约束选择(:y, i)到您传入的数据集中的值ys[i]。这是有效的,因为(:y, i)始终是第 i 个数据点的名称,无论 的值如何:is_line

更新/操作痕迹

你写:

我希望能够从组合中内省 sine/line_model 的迹线,并对迹线进行元素添加以获得新的迹线。并且不必随机选择接近 :intercept、:phase 等的数字,因此我可以稍后将其包含在我的跟踪中。

你当然可以调用simulate两次来获得两条轨迹,在生成函数之外,比如combo. 但是迹线不能以任意方式进行操作(例如“元素相加”):作为数据结构,迹线保持某些不变量,例如始终知道其当前值在生成它们的模型下的确切概率,并始终保存实际可能具有的值由模型生成。

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

observations = Gen.choicemap()
for (i, y) in enumerate(ys)
  observations[(:y, i)] = y
end

Choicemaps 可用作生成新跟踪的约束(使用Gen.generate),作为 Gen 低级Gen.update方法的参数(允许您在重新计算任何相关概率时更新跟踪,并在您的更新无效时出错),以及在其他几个地方.

希望有帮助:)

于 2019-07-08T05:11:33.703 回答
0

感谢 Alex Lew 的澄清,答案比我想象的要简单得多。这是我所做的:

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
于 2019-07-12T04:37:10.460 回答