五个例子掌握theano.scan函数

一、theano的工作原理

    在theano编程中,Graph是指导theano如何对变量进行操作的唯一途径,theano变量和theano Ops(操作)是Graph的两个基本构成元素。Graph只能由theano变量(包括shared变量)或常数组成。如图所示: 

Graph

    通常可以按如下步骤构造Graph:首先声明theano变量,theano变量在Python文件中的作用范围和普通python变量相同;然后用theano的Ops建立变量之间的联系,如T.sum(a,b);最后用theano.function把变量和变量间关系结合起来,构成一个完整的Graph。

    假设已经创建了一个function,称为fn,fn=theano.function(…)。Graph中的shared变量已经包含了调用fn时需要的数据,而普通theano变量仅仅是一个占位符,需要在function中作为输入,并且在调用fn时给变量赋具体值(如numpy的array或者常数)。

二、scan函数

    scan是theano中构建循环Graph的方法,函数声明如下:

theano.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的一步执行。除了outputs_info,fn可以返回sequences变量的更新updates。fn的输入变量顺序为sequences中的变量outputs_info的变量non_sequences中的变量。如果使用了taps,则按照taps给fn喂变量,taps的详细介绍会在后面的例子中给出。

sequences:scan进行迭代的变量;scan会在T.arange()生成的list上遍历,例如下面的polynomial 例子。

outputs_info初始化fn的输出变量,和输出的shape一致;如果初始化值设为None表示这个变量不需要初始值。

non_sequences:fn函数用到的其他变量,迭代过程中不可改变(unchange)。

n_steps:fn的迭代次数。

下面通过几个例子解释scan函数的具体使用方法。

例一、A的k次方

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#  A**k</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>
k = T . iscalar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'k'</span>)
A = T . vector( <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'A'</span>)

outputs, updates = theano.scan(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">lambda</span> result, A : result * A,
             non_sequences = A, outputs_info=T.ones_like(A), n_steps = k)
result = outputs [-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]
fn_Ak = theano . function([A,k ], result, updates=updates )
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">print</span> fn_Ak( range(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span> ), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> )

结果:
[  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">25.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">36.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">49.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">81.</span>]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

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

例二、多项式方程

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># polynomial -- c0*x^0 + c1*x^1 + c2*x^2 + c3*x^3...</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>
coefficients=T.vector(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'coeff'</span>)
x = T.iscalar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'x'</span>)
sum_poly_init = T.fscalar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'sum_poly'</span>)
result, update = theano.scan(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">lambda</span> coefficients, power, sum_poly, x: T.cast(sum_poly +     
                             coefficients*(x**power),dtype=theano.config.floatX),
                             sequences=[coefficients, T.arange(coefficients.size)],
                            outputs_info=[sum_poly_init],
                            non_sequences=[x])

poly_fn = theano.function([coefficients,sum_poly_init,x], result, updates=update)

coeff_value = numpy.asarray([<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6.</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5.</span>], dtype=theano.config.floatX)
x_value = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>
poly_init_value = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">print</span> poly_fn(coeff_value,poly_init_value, x_value)

结果:
[   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">199.</span>]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul>

    这个例子主要演示了T.arange()的作用,scan会在T.arange()生成的list上遍历。例如这段代码中T.arange()生成list=[0,1,2,3],在第i次迭代中,scan把coefficients的第i个元素和list的第i个元素喂给fn作为参数。outputs_info作为第三个参数输入给fn,然后是non_sequences的变量。其中outputs_info的初始化大小和类型都要和fn的返回结果相同。打印结果中包含了4次迭代的输出。

例三、theano.scan_module.until

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># theano.scan_module.until</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">print</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'theano.scan_module.until:'</span>
<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">prod_2</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(pre_value, max_value)</span>:</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> pre_value*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, theano.scan_module.until(pre_value*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> > max_value)

max_value = T.iscalar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'max_value'</span>)
result, update = theano.scan(prod_2, outputs_info=T.constant(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span>),
                             non_sequences=[max_value], n_steps=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>)

prod_fn = theano.function([max_value], result, updates=update)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">print</span> prod_fn(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">400</span>)

结果:
[   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.</span>    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4.</span>    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">32.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512.</span>]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

    theano.scan_module.until必须放在函数的return语句里,当条件满足时,scan停止迭代。

例四、斐波那契数列–taps

    taps在有时间序列的迭代程序中比较有用,例如有如下代码:

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">scan(fn, sequences = [ dict(input= Sequence1, taps = [-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>])
                     , Sequence2
                     , dict(input =  Sequence3, taps = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>) ]
       , outputs_info = [ dict(initial =  Output1, taps = [-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>,-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>])
                        , dict(initial = Output2, taps = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">None</span>)
                        , Output3 ]
       , non_sequences = [ Argument1, Argument2])</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

那么fn函数的变量输入顺序是:

    1. Sequence1[t-3]
    2. Sequence1[t+2]
    3. Sequence1[t-1]
    4. Sequence2[t]
    5. Sequence3[t+3]
    6. Output1[t-3]
    7. Output1[t-5]
    8. Output3[t-1]
    9. Argument1
    10. Argument2

其中sequences默认taps=0;outputs_info默认taps=-1,因为taps=0的结果是当前这一步迭代需要计算的。

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># taps scalar -- Fibonacci sequence</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>
Fibo_arr = T.vector(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'Fibonacci'</span>)
k= T.iscalar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'n_steps'</span>)
result, update = theano.scan(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">lambda</span> tm2,tm1: tm2 + tm1,
                             outputs_info=[dict(initial=Fibo_arr, taps=[-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>])],
                            n_steps=k)
Fibo_fn = theano.function([Fibo_arr,k], result, updates=update)
Fibo_init = numpy.asarray([<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>], dtype=theano.config.floatX)
k_value = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">print</span> Fibo_fn(Fibo_init, k_value)

结果:
[   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.</span>    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.</span>    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5.</span>    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">21.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">34.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">55.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">89.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">144.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">233.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">377.</span>]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

    程序段中首先设置scan的output的初始值为Fibo_arr=[1,1]向量,taps -2和-1分别指向Fibo_arr的第一个元素和第二个元素,并作为匿名函数的输入参数tm2和tm1。例如假设scan迭代到[ 2. 3. 5. 8. 13. 21. 34. ]时,taps=-4对应的值为8,taps=-3对应的值为13,taps=-2对应的值为21,taps=-1对应的值为34,那么在当前迭代中tm2=21, tm1=34,当前迭代结果为21+34=55。

    当使用taps时,outputs_info的初始化值中必须包含taps所对应时间点的值。

例五、两个斐波那契数列

<code class="language-python hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># taps vector -- two Fibonacci sequences</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#==============================================================================</span>
Fibo_mat = T.matrix(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'Fibo_mat'</span>)
k = T.iscalar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'n_steps'</span>)
result, update = theano.scan(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">lambda</span> tm2,tm1: tm2 + tm1,
                              outputs_info=[dict(initial=Fibo_mat, taps=[-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>])],
                            n_steps=k)
Fibo_fn = theano.function([Fibo_mat,k], result, updates=update)
Fibo_init = numpy.asarray([[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>],[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]], dtype=theano.config.floatX)
k_value = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">print</span> Fibo_fn(Fibo_init, k_value)
结果:
[[   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.</span>    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.</span>]
 [   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.</span>    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5.</span>]
 [   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5.</span>    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8.</span>]
 [   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13.</span>]
 [  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">21.</span>]
 [  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">21.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">34.</span>]
 [  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">34.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">55.</span>]
 [  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">55.</span>   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">89.</span>]
 [  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">89.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">144.</span>]
 [ <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">144.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">233.</span>]
 [ <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">233.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">377.</span>]
 [ <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">377.</span>  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">610.</span>]]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li></ul>

    在这段程序中,taps = -2的值为[1,1], taps=-1的值为[1,2],通过迭代求和,得到了两列斐波那契数列。这段代码和例四很相似,只是例四中是标量的迭代,这段代码是向量的迭代,同样可以很容易扩展到矩阵的迭代。

三、参考资料

theano document:http://deeplearning.net/software/theano/library/scan.html#lib-scan-shared-variables

1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值