![](/img/trans.png)
[英]Random numbers error in scan, theano.gof.fg.MissingInputError
[英]Using Random Numbers in Theano
我是theano新手。
有人可以解释下面的代码吗?
from theano.tensor.shared_randomstreams import RandomStreams
from theano import function
srng = RandomStreams(seed=234)
rv_u = srng.uniform((2,2))
rv_n = srng.normal((2,2))
f = function([], rv_u)
g = function([], rv_n, no_default_updates=True) #Not updating rv_n.rng
nearly_zeros = function([], rv_u + rv_u - 2 * rv_u)
state_after_v0 = rv_u.rng.get_value().get_state()
nearly_zeros() # this affects rv_u's generator
v1 = f()
rng = rv_u.rng.get_value(borrow=True)
rng.set_state(state_after_v0)
rv_u.rng.set_value(rng, borrow=True)
v2 = f() # v2 != v1
v3 = f() # v3 == v1
Q1。 near_zeros()如何影响rv_u的生成器?
Q2。 为什么?
v2 != v1
v3 == v1
Q1
看起来rv_u的生成器只生成1“值”(即2x2矩阵)。 如果使用theano.printing.debugprint
打印函数图,则可以看到此信息。 作为参考,这是我得到的:
>>> theano.printing.debugprint(nearly_zeros)
Elemwise{Composite{((i0 + i0) - (i1 * i0))}}[(0, 0)] [@A] '' 1
|RandomFunction{uniform}.1 [@B] '' 0
| |<RandomStateType> [@C]
| |TensorConstant{(2,) of 2} [@D]
| |TensorConstant{0.0} [@E]
| |TensorConstant{1.0} [@F]
|TensorConstant{(1, 1) of 2.0} [@G]
RandomFunction{uniform}.0 [@B] '' 0
这意味着两个函数(almost_zero和f)都只从rv_u中获取1个值,这就是原因
v3 == v1
Q2
Theano主要是一个象征性的数学包。 您定义符号变量之间的关系,Theano计算出如何评估这些关系。
因此,您可以将rv_u视为表示单个2x2矩阵的变量,而不是每次“调用”时生成新的2x2矩阵的rng。 鉴于该视图,Theano只需要调用底层rng一次即可获得变量rv_u的值。
当nearly_zeros()
,它使用随机流的当前rng状态返回一个新的rv_u
并递增状态,就像它对函数f
。 查看rv_u
发生了什么的最简单方法是将其作为输出添加到nearly_zeros()
函数中。 虽然rv_u
存在三次,但rv_u
的值rv_u
随机流中采样一次,因此nearly_zero
确实几乎为零(直到浮点量化误差)。
nearly_zeros = function([], [rv_u, rv_u + rv_u - 2 * rv_u])
f() # The return value will be different from the rv_u in the list above
如果您不打算增加它,可以像对g
一样指定no_default_updates=True
。
nearly_zeros = function([], [rv_u, rv_u + rv_u - 2 * rv_u],
no_default_updates=True)
f() # The return value will be equal to the rv_u in the list above
这里的“为什么”有点含糊不清,所以我提出了两种可能性。
nearly_zeros()
以这种方式影响rv_u
?
rv_u
是一个统一的srng对象,它使用一个共享变量,每次请求时都会递增,除非另有说明(通过no_defalut_updates
参数)。无论f
或nearly_zero
恰好是请求值的函数,都是如此。 rv_u
。
from theano.tensor.shared_randomstreams import RandomStreams
from theano import function
srng = RandomStreams(seed=234)
rv_u = srng.uniform((2,2))
rv_n = srng.normal((2,2))
f = function([], rv_u)
g = function([], rv_n, no_default_updates=True) #Not updating rv_n.rng
nearly_zeros = function([], [rv_u, rv_u + rv_u - 2 * rv_u]) # Give rv_u, too
state_after_v0 = rv_u.rng.get_value().get_state()
nearly_zeros() # this affects rv_u's generator
v1 = f()
rng = rv_u.rng.get_value(borrow=True)
rng.set_state(state_after_v0)
rv_u.rng.set_value(rng, borrow=True)
v2 = f() # v2 != v1, but equal to rv_u used by nearly_zeros
v3 = f() # v3 == v1
这是因为您的代码在定义nearly_zeros
但在调用之前保存状态。 设置状态时,返回的第一个值是nearly_zeros
使用的值(等于v2
。)请求的下一个值将等于v3
的值。 以下是几乎完全相同的代码副本,它应该说明:
from theano.tensor.shared_randomstreams import RandomStreams from theano import function srng = RandomStreams(seed=234) rv_u = srng.uniform((2,2)) rv_n = srng.normal((2,2)) f = function([], rv_u) g = function([], rv_n, no_default_updates=True) #Not updating rv_n.rng nearly_zeros = function([], [rv_u, rv_u + rv_u - 2 * rv_u]) # Give rv_u, too state_after_v0 = rv_u.rng.get_value().get_state() nearly_zeros() # this affects rv_u's generator v1 = f() rng = rv_u.rng.get_value(borrow=True) rng.set_state(state_after_v0) rv_u.rng.set_value(rng, borrow=True) v2 = f() # v2 != v1, but equal to rv_u used by nearly_zeros v3 = f() # v3 == v1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.