Theano定义了一个重复调用另一个函数的函数?

3
我的培训功能:
def fit(self, X, y):
    batch_size = 20

    index = T.lscalar()  # index to a [mini]batch
    updates = {}

    return theano.function(
        inputs=[index], outputs=self.cost, updates=updates,
        givens={
            self.sym_X: X[index * batch_size:(index + 1) * batch_size],
            self.sym_y: y[index * batch_size:(index + 1) * batch_size]})

然后来自其他地方:
fn = obj.fit(X, y)
for i in range(10):
    fn(i)

我希望你们能够帮我实现这样的效果:

如下图所示


fn = obj.fit(X, y)
fn()

我真的不确定如何开始,因为对于我来说theano仍然非常晦涩难懂。我已经做到了这一步,但是循环确实是一个严峻的挑战。

我有一个模糊的想法,如果我可以将theano.function转换成theano.scan,然后在外面放一个theano.function - 那可能会起作用。但是,尽管我已经付出了最大的努力,theano.scan 对我来说仍然神秘。

我该如何使迭代小批量数据集合并到单个函数调用中?

更新:

我以为我做到了!我得到了这个:

def fit(self, X, y):
    batch_size = 20
    n_batches = 5

    index = theano.shared(0)

    ## index to a [mini]batch
    updates = {
        index: index + batch_size
    }

    return theano.function(
        inputs=[], outputs=[self.cost] * n_batches, updates=updates,
        givens={
            index: 0,
            self.sym_X: X[index * batch_size:(index + 1) * batch_size],
            self.sym_y: y[index * batch_size:(index + 1) * batch_size]})

不幸的是,由于我在给定中使用索引来计算批处理,因此我无法对其进行更新:

Traceback (most recent call last):
  File "skdeeplearn/classifiers/test/test_classifiers.py", line 79, in test_logistic_sgd
    fn = clf.fit(self.shared_X, self.shared_y)
  File "skdeeplearn/classifiers/logistic_sgd.py", line 139, in fit
    self.sym_y: y[index * batch_size:(index + 1) * batch_size]})
  File "/Users/aelaguiz/workspace/pyvotune/venv/lib/python2.7/site-    packages/theano/compile/function.py", line 206, in function
    profile=profile)
  File "/Users/aelaguiz/workspace/pyvotune/venv/lib/python2.7/site-packages/theano/compile/pfunc.py", line 461, in pfunc
    no_default_updates=no_default_updates)
  File "/Users/aelaguiz/workspace/pyvotune/venv/lib/python2.7/site-packages/theano/compile/pfunc.py", line 162, in rebuild_collect_shared
    "to be replaced by %s." % (v_orig, v_repl))
AssertionError: When using 'givens' or 'replace' with several (old_v, new_v) replacement pairs, you can not have a new_v variable depend on an old_v one. For instance, givens = {a:b, b:(a+1)} is not allowed. Here, the old_v <TensorType(int64, scalar)> is used to compute other new_v's, but it is scheduled to be replaced by <TensorType(int64, scalar)>.

更新2:
def fit(self, X, y):
    batch_size = 20
    n_batches = 5

    index = theano.shared(0)

    ## index to a [mini]batch
    updates = {
        index: index + batch_size
    }

    return theano.function(
        inputs=[], outputs=[self.cost] * n_batches, updates=updates,
        givens={
            self.sym_X: X[index * batch_size:(index + 1) * batch_size],
            self.sym_y: y[index * batch_size:(index + 1) * batch_size]})

这段代码实际上可以运行,但它的输出结果很奇怪:

[array(0.6931471824645996, dtype=float32), array(0.6931471824645996, dtype=float32), array(0.6931471824645996, dtype=float32), array(0.6931471824645996, dtype=float32), array(0.6931471824645996, dtype=float32)]

每次运行它时,即使在每次运行时X和y都被初始化为随机值,我仍然得到相同的输出。

我基本上已经决定了,目前以我想要的方式做这件事是不可能的。我实际上已经将代码用theano.scan写好了,但后来发现我无法推进X的索引,因为theano不支持在操作内部进行高级索引。因此,我将采取预先对输入进行小批量分组作为预处理操作的方法。 - amirpc
1个回答

5

我认识的每个人都在Python中循环处理小批量数据。这可以使用scan完成,但是你所有尝试都没有使用scan。因此,它们无法正常工作。你需要在某个地方调用scan函数才能使用它(或其高级接口,如map)。实际上,在你的情况下,我认为你可以使用theano.scan(fn, theano.tensor.arange(N))

由于代码片段不完整,我无法回答你所有的问题,但是这里有一些信息:

return theano.function(
    inputs=[], outputs=[self.cost] * n_batches,

这里的[self.cost] * n_batches是纯Python代码。它创建了一个包含n_batches个元素的列表,其中每个元素都是self.cost。所以如果n_batches是3,你会得到outputs=[self.cost, self.cost, self.cost]。这就是为什么你会得到多次相同值的输出。
我无法告诉你为什么你总是添加相同的答案,因为我需要更多的信息才能确定。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接