Theano - 平方渐变的平均值

时间:2016-03-23 11:26:26

标签: neural-network gradient theano

在theano中,给定具有形状(batch_size,)的批量成本cost,可以很容易地计算平均成本的梯度,如T.grad(T.mean(cost,axis=0),p)中那样,p是计算中使用的参数cost。这通过计算图反向传播梯度来有效地完成。我现在要做的是计算批次上平方梯度的平均值。这可以使用以下代码完成:

import theano.tensor as T

g_square = T.mean(theano.scan(lambda i:T.grad(cost[i],p)**2,sequences=T.arange(cost.shape[0]))[0],axis=0)

为方便起见p假设是单个theano张量而不是张量列表。 通过简单地反向传播梯度直到最后一步,并且平方最后一个操作的组件(应该是批次索引的总和),可以有效地执行计算。我可能在这个问题上错了,但计算应该像简单的反向传播一样容易,而且几乎一样快。然而,theano似乎无法优化计算,并且它继续使用循环,使计算极其缓慢。

是否有人知道通过强制优化,以不同方式表达计算,甚至进行反向传播过程来提高计算效率的解决方案?

提前致谢。

2 个答案:

答案 0 :(得分:2)

您的函数g_square碰巧具有复杂度O(batch_size ** 2)而不是O(batch_size)。这使得对于较大的批量大小,它看起来非常慢。

原因是因为在每次迭代中,即使只需要cost[i]一个数据点,也会在整个批次中计算前向和后向传递。 我假设cost计算图x的输入是一个张量,第一维的大小为batch_size。 Theano没有办法沿着这个维度自动切割这个张量。因此,计算总是在整批中进行。

不幸的是,我认为没有比切片输入和在Theano之外进行循环更好的解决方案了:

# x: input data batch
batch_size = x.shape[0]
g_square_fun = theano.function( [p], T.grad(cost[0],p)**2) 

g_square_value = 0
for i in batch_size:
    g_square_value += g_square_fun( x[i:i+1])

也许当The​​ano的未来版本具有更好的计算雅可比行列式的能力时,会有更优雅的解决方案。

答案 1 :(得分:0)

在深入研究Theano文档后,我找到了一个在计算图中工作的解决方案。关键思想是在扫描函数内克隆网络图,从而明确切片输入张量。我尝试了以下代码,根据经验,它显示了O(batch_size):

 # x: input data batch
 # assuming cost = network(x,p)

 from theano.gof.graph import clone_get_equiv

 def g_square(cost,p):

    g = T.zeros_like(p)

    def scan_fn( i, g, cost, p):
        # clone the graph computing cost, but slice it's input 
        cloned = clone_get_equiv([],[cost], 
                                 copy_inputs_and_orphans=False,
                                 memo={x: x[i:i+1]})
        cost_slice = cloned[cost].reshape([])
        return  g+T.grad(cost_slice,p)**2 

    result,updates = theano.reduce( scan_fn,
                                    outputs_info=g,
                                    sequences=[T.arange(cost.size)],
                                    non_sequences=[cost.flatten(),p])

    return result