一、Theano的局限性
Theano代码编写比较灵活,但是也存在一些局限性:
1、while和if循环必须通过theano.scan()操作实现,从而循环的主体会受到一些限制;
2、不支持goto和递归。
所以对于某些矩阵操作需要coder选择合适的方法解决。下面通过两种生成斐波那契数列的方法来讲解scan的使用:
import theano
import theano.tensor as T
from theano import function
import numpy
二、迭代输出
X = T.dvector('X')
results, updates = theano.scan(lambda xtm2, xtm1: xtm2 + xtm1, n_steps = 20, outputs_info=[dict(initial=X, taps=[-2, -1])]) #在迭代过程中保存X[t-2],X[t-1]的值
fibFn = function([X], results, updates = updates)
xval = numpy.ones(2, dtype=theano.config.floatX)
print xval
print fibFn(xval)
scan函数的第一个参数fn的输入依次为sequences、outputs_info、non_sequences。函数返回值:(outputs, updates)。
变量X中保留了t-2和t-1时刻的结果,并且在初始化的时候这两个值都设置为1,所以可以在scan函数中计算X[t] = X[t-2] + X[t-1] (xtm2 + xtm1)。
输出结果:
[ 1. 1.]
[ 2.00000000e+00 3.00000000e+00 5.00000000e+00 8.00000000e+00
1.30000000e+01 2.10000000e+01 3.40000000e+01 5.50000000e+01
8.90000000e+01 1.44000000e+02 2.33000000e+02 3.77000000e+02
6.10000000e+02 9.87000000e+02 1.59700000e+03 2.58400000e+03
4.18100000e+03 6.76500000e+03 1.09460000e+04 1.77110000e+04]
三、矩阵操作
上面的代码每次迭代直接输出一个结果,也可以在矩阵中保留所有斐波那契数。
X = T.dvector('X')
def Fib(i,X):
....X = T.set_subtensor(X[i], X[i-1]+X[i-2])
....return X
result, update = theano.scan(Fib , sequences = T.arange(2,X.size), outputs_info = [X])
fibFunc = function([X], result[-1], updates = update)
xval = numpy.zeros(20, dtype=theano.config.floatX)
xval[0] = 1
xval[1] = 1
print fibFunc(xval)
把sequences 和outputs_info的变量作为Fib(i,X)函数的输入,在Fib函数中计算下一个数组元素的值,function的result[-1]告诉Theano我们只需要最后一个向量。
输出结果:
[ 1.00000000e+00 1.00000000e+00 2.00000000e+00 3.00000000e+00
5.00000000e+00 8.00000000e+00 1.30000000e+01 2.10000000e+01
3.40000000e+01 5.50000000e+01 8.90000000e+01 1.44000000e+02
2.33000000e+02 3.77000000e+02 6.10000000e+02 9.87000000e+02
1.59700000e+03 2.58400000e+03 4.18100000e+03 6.76500000e+03]