theano-scan:如何 outputs_info 将占位符提要作为输入

theano-scan: how outputs_info with placeholder feed as input

我对 theano 中的 outputs_info 扫描感到困惑。下面是计算 A**k 的扫描示例:

k = T.iscalar("k")
A = T.vector("A")
def inner_fct(prior_result, B):
    return prior_result * B
# Symbolic description of the result
result, updates = theano.scan(fn=inner_fct,
                            outputs_info=T.ones_like(A),
                            non_sequences=A, n_steps=k)
# Scan has provided us with A ** 1 through A ** k.  Keep only the last
# value. Scan notices this and does not waste memory saving them.
final_result = result[-1]
power = theano.function(inputs=[A, k], outputs=final_result,
                      updates=updates)
print(power(range(10), 2))

我做了如下小改动:

k = T.iscalar("k")
A = T.vector("A")
def inner_fct(prior_result, B):
    return B, B, prior_result * B   #!! change return of inner_fct
#!! change scan as below
[B1, B2, result], updates = theano.scan(fn=inner_fct,
                            outputs_info=[None, None, T.ones_like(A)],
                            non_sequences=A, n_steps=k)
final_result = result[-1]
power = theano.function(inputs=[A, k], outputs=final_result,
                      updates=updates)
print(power(range(10), 2))

它仍然得到与原始结果相同的结果。当我更改 outpus_info=[None, T.ones_like(A), None] 或 ouputs_info=[T.ones_like(A), None, None], 还是一样的结果。 T.ones_like(A) 将作为 inner_fct 中 prior_result 的首字母,所以我可以假设 theano 会找到一个不是 None 的首字母作为 prior_result 的首字母]?

theano 究竟是如何选择 outputs_info 中的首字母作为输入的?

k = T.iscalar("k")
A = T.vector("A")
def inner_fct(prior_result, B):
    return B, prior_result*B, prior_result * B   #!! change return of inner_fct
#!! change scan as below
[B1, B2, result], updates = theano.scan(fn=inner_fct,
                            outputs_info=[None, None, T.ones_like(A)],
                            non_sequences=A, n_steps=k)
power = theano.function(inputs=[A, k], outputs=[B2,result],
                      updates=updates)
print(power(range(10), 2))

outputs_info中的第二个参数是None,这意味着inner_fct的第二个输出不是循环的,但是print(power(range(10), 2))表明B2是循环的与 result.

相同

outputs_info 就像 the documentation 说的那样有效。

特别是,

outputs_info is the list of Theano variables or dictionaries describing the initial state of the outputs computed recurrently.

并且

If you provide a None instead of a variable or a empty dictionary scan assumes that you will not use any taps for this output (like for example in case of a map)

outputs_info 列表中的元素数量应与 scan 步进函数返回的值数量相匹配。在您的第一个示例中,阶跃函数 returns 是单个值,因此 outputs_info 应该(并且确实)包含单个元素。在你的第二个例子中,阶跃函数 returns 三个值所以 outputs_info 应该(并且确实)包含三个元素。

对于 outputs_info 中的每个值,如果它是 None 则表示该值不是循环的(此位置的输出不可用于以后的迭代)。一个非None outputs_info的值表示那个位置的步进输出是循环的,提供的值是传递给步进函数的初始值在第一步;后续步骤接收上一步的输出。

所以 scan 并没有做一些聪明的魔术来自动找出哪个元素包含初始值。在第二个示例中,您只是简单地告诉 Theano 做一些特定的事情,阶跃函数 returns 两个非循环值(因此有两个 Nones)后跟一个循环值(因此初始值在第三个位置)。

在第三个示例中(在问题编辑中添加),步进函数(第三个)仍然只有一个循环输出。 outputs_info 值决定了哪些输出是循环的,在第三个例子中,只有一个非 None outputs_info 值。 B2函数输出和result函数输出相同,因为它们有相同的计算表达式:prior_result*B。这两个值中的哪一个被迭代并不重要,它们始终保持相同。