theano tutorial(六)Loop

来源:互联网 发布:最近很火的网络音乐 编辑:程序博客网 时间:2024/04/26 07:49

Scan

1.reduction 和 map 是 scan 的特例

2.scan一个输入序列,每一个step输出一个output

3.sum()可以通过对整个函数进行z+x(i)操作,z的初值为0

4.scan是theano对looping的封装

5.使用scan的优势:

       迭代此时可以成为symbolic graph的一部分

       减少GPU的转换次数

       在一个序列的每一步计算一个梯度值

       通过监测实际的内存使用来减少总的内存消耗

scan在计算的时候,可以访问以前n步的输出结果

scan定义


# def scan(fn,#          sequences=None,#          outputs_info=None,#          non_sequences=None,#          n_steps=None,#          truncate_gradient=-1,#          go_backwards=False,#          mode=None,#          name=None,#          profile=False,#          allow_gc=None,#          strict=False):#fn:定义了进行scan的操作的函数对象,函数可以在外部定义好,也可以在内部再定义.在内部在定义的fn一般用lambda来定义需要用到的参数,在外部就def好的函数,fn直接函数名即可。#sequences:就是需要迭代的序列(输入序列),它的值将会传给fn作为前面的参数。如果在output_info里有initial,那这个参数可以省略。#outputs_info描述了需要用到的初始化值,以及是否需要用到前几次迭代输出的结果,dict(initial=X, taps=[-2, -1])表示使用序列x作为初始化值,taps表示会用到前一次和前两次输出的结果。如果当前迭代输出为x(t),则计算中使用了(x(t-1)和x(t-2)。#non_sequences:描述了非序列的输入(参数),它的值传给fn后面的参数,且每次迭代的A都是不变的。#lambda匿名函数,感觉有点像函数对象#shape[i]第i维的长


# Scanimport theanoimport theano.tensor as Timport numpy as npX=T.matrix('X')W=T.matrix('W')b_sym=T.vector("b_sym")#return:(outputs_list, update_dictionary)#outputs_list,和output_info(outputs的初始状态)顺序的一样#update_dictionary怎样在每个迭代步骤之后shared 变量results,updates=theano.scan(lambda v:T.tanh(T.dot(v,W)+b_sym),sequences=X)compute_elementwise=theano.function(inputs=[W,X,b_sym],outputs=results)x=np.eye(2,dtype=theano.config.floatX)w=np.ones((2,2),dtype=theano.config.floatX)b = np.ones((2), dtype=theano.config.floatX)b[1] = 2 print(compute_elementwise(x, w, b))# 和numpy计算出的结果一样print(np.tanh(x.dot(w) + b))

每次

#coding=utf-8import theanoimport theano.tensor as Timport numpy as np# define tensor variablesX = T.vector("X")W = T.matrix("W")b_sym = T.vector("b_sym")Y = T.matrix("Y")results, updates = theano.scan(lambda y,x_tm1: T.dot(x_tm1, W),          sequences=[Y], outputs_info=[X])compute_seq = theano.function(inputs=[X, W, Y], outputs=results)# test valuesx = np.zeros((2), dtype=theano.config.floatX)x[1] = 1w = np.ones((2, 2), dtype=theano.config.floatX)y = np.ones((5, 2), dtype=theano.config.floatX)y[0, :] = -3print(compute_seq(x, w, y))# comparison with numpyx_res = np.zeros((5, 2), dtype=theano.config.floatX)x_res[0] = x.dot(w)for i in range(1, 5):    x_res[i] = x_res[i - 1].dot(w)print(x_res)
把官网教程里面的改了,比较好比较结果,每次抽取一个output_info 形式的作为一个step进行计算
[[  1.   1.] [  2.   2.] [  4.   4.] [  8.   8.] [ 16.  16.]][[  1.   1.] [  2.   2.] [  4.   4.] [  8.   8.] [ 16.  16.]]

更好的理解sequence和output_info

#coding=utf-8import theanoimport theano.tensor as Timport numpy as np# define tensor variablesX = T.vector("X")W = T.matrix("W")b_sym = T.vector("b_sym")U = T.matrix("U")Y = T.matrix("Y")V = T.matrix("V")P = T.matrix("P")# results, updates = theano.scan(lambda y, p, x_tm1: T.tanh(T.dot(x_tm1, W) + T.dot(y, U) + T.dot(p, V)),#           sequences=[Y, P[::-1]], outputs_info=[X])#outputs_info=[X]代表公式中的x(t-1)#注意以下P[::-1]的用法#下面改写一下sequence和outputs_info,结果是一样的results, updates = theano.scan(lambda y, p, x_tm1: T.tanh(T.dot(x_tm1, W) + T.dot(y, U) + T.dot(p, V)),           sequences=[dict(input=Y,taps=[0]), P[::-1]], outputs_info=[dict(initial=X,taps=[-1])])compute_seq = theano.function(inputs=[X, W, Y, U, P, V], outputs=results)# test valuesx = np.zeros((2), dtype=theano.config.floatX)x[1] = 1w = np.ones((2, 2), dtype=theano.config.floatX)y = np.ones((5, 2), dtype=theano.config.floatX)y[0, :] = -3u = np.ones((2, 2), dtype=theano.config.floatX)p = np.ones((5, 2), dtype=theano.config.floatX)p[0, :] = 3v = np.ones((2, 2), dtype=theano.config.floatX)print(compute_seq(x, w, y, u, p, v))# comparison with numpyx_res = np.zeros((5, 2), dtype=theano.config.floatX)x_res[0] = np.tanh(x.dot(w) + y[0].dot(u) + p[4].dot(v))for i in range(1, 5):    x_res[i] = np.tanh(x_res[i - 1].dot(w) + y[i].dot(u) + p[4-i].dot(v))print(x_res)


Computing norms of lines of X
#coding=utf-8import theanoimport theano.tensor as Timport numpy as npX=T.matrix("X")#注意这里貌似抽取的是X的一行,如果要抽取一列应该是sequences=[X.T]results,updates=theano.scan(lambda x_i:T.sqrt((x_i**2).sum()),sequences=[X])compute_norm_lines=theano.function(inputs=[X],outputs=results)#diag(v,k)如果k>0,对角线在主轴上面,k<0在下面x=np.diag(np.arange(1,6,dtype=theano.config.floatX),1)print(compute_norm_lines(x))print(np.sqrt(x**2).sum(1))


[ 1.  2.  3.  4.  5.  0.][ 1.  2.  3.  4.  5.  0.]


0 0