小小千想和您聊一聊

当前位置: 首页> 技术分享> Python视频教程之Theano中的循环

Python视频教程之Theano中的循环

  循环是程序语言中重要的模块之一,Theano的循环操作使用scan模块来实现。scan模块类似于Python的for语句,接下来,本节将对Theano中的循环语句进行讲解(由于scan的参数众多,本书将只对几个相对重要的参数进行讲解,其他参数可以通过访问theano官方文档进一步了解)。

  scan循环的参数

  scan循环的参数有很多,本书仅对以下几个主要参数进行讲解:sequences,outputs_info,non_sequences,fn,n_steps,truncate_gradient,strict。

  1.sequences

  sequences是一个由Theano变量或字典构成的列表,他们的值将作为参数传递给函数fn。列表中的每一个元素都是一个序列,每一次迭代可以传递序列的一个元素或多个元素,具体示例代码如下所示。

  >>> theano.scan(……,

  sequences=[dict(input=sequence1,taps=[-1,-2]),

  sequences2,

  dict(input=sequence3,taps = 3)],

  ……)

  上述代码的sequences参数包含了以下三个参数:sequence1、sequence2、sequence3三个输入序列。

  sequence1:通常以字典的形式表示,字典中可以包括input(输入序列)和taps(索引)两个key值。上述代码表示在第t次迭代时,sequence1传递给fn的参数有sequence1[t-1]和sequence1[t-2]。

  sequence2:以普通的Theano变量形式传递,该参数等价于下列代码。

  dict(input = squence2,taps=[0])

  当忽略taps参数时,Theano会默认taps的值为0,因此,在第t次迭代时,sequence2传递给fn的参数为sequence2[t]。

  sequence3:结合前两个参数的传递过程可以看出,在第t次迭代时,sequence3传递给fn的参数为sequence3[t+3]。

  2.outputs_info

  与sequences的表达相似,outputs_info也是一个由Theano变量或字典构成的列表,列表中的每一个元素是函数fn的输出结果的初始值,具体示例如下所示。

  >>>theano.scan(……,

  outputs_info = [ dict(initial = output1, taps = [-3,-5]),

  output2,

  dict(initial = output 3,taps = 3)]

  ……)

  上述代码的sequences参数包含了以下三个参数:output1,output2,output3

  output1:以字典的形式进行表示。用字典形式表示outputs_info时,可以包括initial(定义初始值)和taps(索引)两个key值。表示在第t次迭代时,output1传递给fn的参数为output1[t-3]和output1[t-5]。

  output2:以普通的Theano变量形式传递,该参数等价于下列代码。

  dict(initial = output2,taps=[-1])

  与前面提到的sequence2情况一样,在忽略taps的值时,系统会为taps自动添加默认值,但是要注意,这里的taps默认值为-1。表示在第t次迭代时,output2传递给fn的参数为output2[t-1]。

  output3:结合前两个参数的传递过程可以看出,output3表示在第t次迭代时,传递给fn的参数为sequence3[t+3]。

  3.non_sequences

  该参数是一个不变量或常数值列表,与前两个参数不同,该参数在迭代过程中不可改变。在实际应用中,一般把该参数设置为模型的权重参数列表。

  4.fn

  该参数是一个函数,fn是scan最核心的组成部分,它定义了每一次循环的处理逻辑,可以返回sequences变量的更新updates。fn既可以用lambda匿名函数来表示,也可以通过自定义函数表示。fn对函数参数的定义顺序和函数输出有严格对应的要求,输入变量顺序为sequences中的变量,outputs_info的变量,non_sequences中的变量。

  5.n_steps

  用来指定scan的迭代次数。sequences与n_steps两个参数中至少存在一个,否则scan无法知道迭代的步数。

  6.truncate_gradient

  这是一个专为循环神经网络训练设计的参数。利用scan来实现BPTT时,truncate_gradient用于指定向前传播的步长值,当值为-1时,表示采用的是传统的BPTT算法;当值大于0时,表示向前执行步长达到truncate_gradient设定值时,会提前结束并返回。这种截断策略可以用于处理传统的BPTT中的梯度消失问题。

  7.strict

  当该参数的值为True时,必须保证所有用到的Theano共享变量都放置在non_sequences参数中。

  scan循环演示

  一般情况下,一个for循环可以表示成一个scan()操作,而且scan是与theano的循环联系最紧密的。使用scan而不是for循环的优势:

  迭代的次数是符号graph的一部分。

  最小化GPU的迁移(如果用到GPU的话)。

  通过连续的步骤计算梯度。

  比python中使用theano编译后的for循环稍微快一点。

  通过检测实际用到的内存的数量,来降低总的内存使用情况。

  接下来通过几个案例来帮助理解scan的使用方法。

  以逐元素计算为例,通过scan循环演示计算A的k次方。

  import theano

  import theano.tensor as T

  k = T.iscalar('k')

  A = T.vector('A')

  outputs, updates = theano.scan(lambda result, A : result * A,

  non_sequences = A,

  outputs_info=T.ones_like(A), n_steps = k)

  result = outputs [-1]

  fn_Ak = theano.function([A,k], result, updates=updates)

  print(fn_Ak(range(10), 2))

  运行结果如下所示。

  [ 0. 1. 4. 9. 16. 25. 36. 49. 64. 81.]

  上述程序中outputs_info初始化为于A大小相同的全1向量,匿名函数(lambda)的输入依次为outputs_info和non_sequences,分别对应于匿名函数的输入result和A。由于scan函数的输出结果会记录每次迭代fn的输出,result = outputs [-1]表示Theano只需要取最后一次迭代结果,Theano也会对此做相应的优化(不保存中间迭代结果)。

上一篇:HTML5工具初识之网页编辑器

下一篇:Unity可以用svn吗