使用theano内的扫描建立矩阵

时间:2015-10-29 17:46:04

标签: theano

我非常肯定这是微不足道的,但我还没有成功地完全理解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.])

1 个答案:

答案 0 :(得分:0)

这里有一些指向一些误解的东西。 scan真的可以成为Theano的一大部分来包围你的头脑!

这是一些更新的代码,可以执行我认为您正在尝试执行的操作,但我不建议您使用此代码。基本问题是您似乎不恰当地使用共享变量。

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.function的{​​{1}}参数。如果没有这个,共享变量将根本不会更新。

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

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

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

    updates

    这是高度简化的,我不建议真正使用它。一般来说,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进行动态编程。

    如果你想要一个更全面的DTW实现来克服一些性能命中,Theano通过并行计算许多比较(即批处理)来强加,那么请看一下:https://github.com/danielrenshaw/TheanoBatchDTW