一、theano的工作原理
在theano编程中,Graph是指导theano如何对变量进行操作的唯一途径,theano变量和theano Ops(操作)是Graph的两个基本构成元素。Graph只能由theano变量(包括shared变量)或常数组成。如图所示:
通常可以按如下步骤构造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
-
踩