【问题标题】:Buidling matrix using scan within theano在 theano 中使用扫描构建矩阵
【发布时间】:2015-10-30 04:59:58
【问题描述】:

我很确定这是微不足道的,但我还没有完全理解scan。我想迭代地构建一个值矩阵,m,其中

m[i,j] = f(m[k,l]) for k < i, j < l

所以你可以把它想象成一个动态规划问题。但是,我什至无法通过迭代列表 [1..100] 并随时更新共享值来生成列表 [1..100]。

import numpy as np
import theano as T
import theano.tensor as TT

def test():
    arr = T.shared(np.zeros(100))
    def grid(idx, arr):
        return {arr: TT.set_subtensor(arr[idx], idx)}

    T.scan(
        grid,
        sequences=TT.arange(100),
        non_sequences=[arr])

    return arr

run = T.function([], outputs=test())
run()

返回

array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

【问题讨论】:

    标签: theano


    【解决方案1】:

    这里有几件事指向一些误解。 scan 真的很难缠住你的脑袋!

    这里有一些更新的代码,可以完成我认为您正在尝试做的事情,但我根本不建议使用此代码。基本问题是您似乎不恰当地使用了共享变量。

    import numpy as np
    import theano as T
    import theano.tensor as TT
    
    def test():
        arr = T.shared(np.zeros(100))
        def grid(idx, arr):
            return {arr: TT.set_subtensor(arr[idx], idx)}
    
        _, updates = T.scan(
            grid,
            sequences=TT.arange(100),
            non_sequences=[arr])
    
        return arr, updates
    
    outputs, updates = test()
    run = T.function([], outputs=outputs, updates=updates)
    print run()
    print outputs.get_value()
    

    此代码在两个方面与原始代码不同:

    1. 必须捕获来自扫描的更新(最初丢弃)并传递给theano.functionupdates 参数。没有这个,共享变量根本不会被更新。

    2. 函数执行后需要检查共享变量的内容(见下文)。

    此代码打印两组值。第一个是 Theano 函数执行时的输出。第二个是 Theano 函数执行后共享变量的内容。 Theano 函数返回共享变量,因此您可能认为这两组值应该相同,但您错了!直到计算出所有函数的输出值之后,才会更新共享变量。所以只有在函数执行之后,我们查看共享变量的内容,才能看到我们最初期望看到的值。

    这是在 Theano 中实现动态规划算法的示例。该算法是动态时间扭曲的简化版本,与编辑距离有很多相似之处。

    import numpy
    import theano
    import theano.tensor as tt
    
    
    def inner_step(j, c_ijm1, i, c_im1, x, y):
        insert_cost = tt.switch(tt.eq(j, 0), numpy.inf, c_ijm1)
        delete_cost = tt.switch(tt.eq(i, 0), numpy.inf, c_im1[j])
        match_cost = tt.switch(tt.eq(i, 0), numpy.inf, c_im1[j - 1])
        in_top_left = tt.and_(tt.eq(i, 0), tt.eq(j, 0))
        min_c = tt.min(tt.stack([insert_cost, delete_cost, match_cost]))
        c_ij = tt.abs_(x[i] - y[j]) + tt.switch(in_top_left, 0., min_c)
        return c_ij
    
    
    def outer_step(i, c_im1, x, y):
        outputs, _ = theano.scan(inner_step, sequences=[tt.arange(y.shape[0])],
                                 outputs_info=[tt.constant(0, dtype=theano.config.floatX)],
                                 non_sequences=[i, c_im1, x, y], strict=True)
        return outputs
    
    
    def main():
        x = tt.vector()
        y = tt.vector()
        outputs, _ = theano.scan(outer_step, sequences=[tt.arange(x.shape[0])],
                                 outputs_info=[tt.zeros_like(y)],
                                 non_sequences=[x, y], strict=True)
        f = theano.function([x, y], outputs=outputs)
        a = numpy.array([1, 2, 4, 8], dtype=theano.config.floatX)
        b = numpy.array([2, 3, 4, 7, 8, 9], dtype=theano.config.floatX)
        print a
        print b
        print f(a, b)
    
    
    main()
    

    这是高度简化的,我不建议真正使用它。一般来说,Theano 在动态编程方面非常糟糕,因为与原生循环相比,theano.scan 非常慢。如果您需要通过动态程序传播渐变,那么您可能别无选择,但如果您不需要渐变,您可能应该避免使用 Theano 进行动态规划。

    如果您想要一个更彻底的 DTW 实现,它通过并行计算许多比较(即批处理)来克服 Theano 施加的一些性能损失,那么请看这里:https://github.com/danielrenshaw/TheanoBatchDTW

    【讨论】:

      猜你喜欢
      • 2017-11-11
      • 2016-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-19
      相关资源
      最近更新 更多