Theano---scan函数

         def scan:

         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描述了迭代的输出结果的公式。传给
        的变量顺序如下所示


        * 第一个sequence
        * 第一个sequence
        * ...
        * 最后一个sequence
        * 第一个output
        * 第二个output
        * ...
        * 最后一个output
        * 所有其他参数 (non_sequence给出)


         sequences的顺序和输入给scan的列表‘sequences’一样
         outputs的顺序“outputs_info”的顺序一样。

         对每个sequence 或者output来说,time slices的顺序和taps里给出的顺序一样
        如下例所示
       

        .. code-block:: python


            scan(fn, sequences = [ dict(input= Sequence1, taps = [-3,2,-1])
                                 , Sequence2
                                 , dict(input =  Sequence3, taps = 3) ]
                   , outputs_info = [ dict(initial =  Output1, taps = [-3,-5])
                                    , dict(initial = Output2, taps = None)
                                    , Output3 ]
                   , non_sequences = [ Argument1, Argument2])


        ``fn`` 中参数的顺序由上到下所示:


        #. ``Sequence1[t-3]``
        #. ``Sequence1[t+2]``
        #. ``Sequence1[t-1]``
        #. ``Sequence2[t]``
        #. ``Sequence3[t+3]``
        #. ``Output1[t-3]``
        #. ``Output1[t-5]``
        #. ``Output3[t-1]``
        #. ``Argument1``
        #. ``Argument2``


        ``non_sequences``列表也可以包括shared参数,
       但是scan通常直接忽略他们。
        为了方便理解,我们通常显示的把shraed变量传给 scan
        ``scan`` 也可以计算出其他的``non sequences`` (非 shared)
        即使他们没有被传给scan (但被`fn`使用). 如下所示:


        .. code-block:: python
            #是2还是W?
            import theano.tensor as TT
            W   = TT.matrix()
            W_2 = W**2
            def f(x):
                return TT.dot(x,W_2)


        这个函数做了两件事,首先它给出了
        一个ouputs list,其顺序和output_info一致,
        区别在在于对每一个output initial state,只有一
        个output 变量(即使没有是使用tap value),第二,
        `应该返回一个update 字典(定义来怎样在每一
        u次迭代后更新shared变量)。shared 变量可以定义为
        一个元组构成的列表。对这两个列表的顺序并没有
        过多的限制。’fn‘可以返回``(outputs_list, update_dictionary)`` 
        或者仅仅是其中的一个
        




    sequences
        ``sequences`` 是一个theano变量或者字典,它描述了
        进行迭代的对象。如果一个序列是以字典的
        形式给出的,那么会有以下可选的参数信息
        
        


        * ``input`` (*mandatory*) -- 代表了输入序列
          


        * ``taps`` -- 代表本次输入使用来第k个输入
           默,例如[-2,-1]代表使用了x[t-2]和x[t-1],默认值为0,


        


    outputs_info
        ``outputs_info`` 代表了每次outputs的初始状态
        当初始状态为字典时,有以下可选信息
        
        keys:


        * ``initial`` -- 代表了给定output的初始状态
          如果output是循环计算,并且不需要初始
          状态的话,可以忽略。假设fn只用了上一次
         输出,那么初始状态应该和output的形式
          相同,并且不应该对output进行向下的类型
         转换。如果使用了多个time taps,初始
          状态应该包括所以的可能的taps.例如,
         如果使用-5,-2,-1作为past taps,在step0,fn
          应该使用``output[-5]``,``output[-2]`` 和 ``output[-1]``
       作为初始状态
          

      * ``taps`` -- 传给fn的output的tap



        ``scan`` 满足下列规则:


        *如果output不是一个字典,那么‘scan’默认你总是使用最后一步输出
         (即 tap=-1)
      
        * 如果你将output放在一个字典里面,提供了初始状态但不提供任何的taps
           那么默认使用tap=-1
          
        * 如果你将output方在一个字典里面,但不提供初始状态,
          默认不使用taps
         
        * 如果使用一个空的字典或者None,默认不使用taps
          
          


        如果``outputs_info`` 是空列表或者None,默认所有的ouputs不使用taps.
        如果只对output的子集提供某些信息,那么将发生错误(因为没有规定如何
        将提供的信息传递给scan
        


    non_sequences
        ``non_sequences`` 描述了非序列的输入(参数),它的值传给fn后面的参数,且每次迭代的A都是不变的。


    n_steps
        ``n_steps`` 迭代次数


   
    返回
    -------
    元组

        outputs, updates)形式的元组或者一个列表
       列表中是scan的输出(和outputs_info)顺序一致
        
        ``updates`` 是一个字典的子集,规定了所有shared变量更新的规则
         在编译的的时候,这个字典将被传递给theano.function



程序示例

import theano
import theano.tensor as T

k = T.iscalar("k")
A = T.vector("A")

# Symbolic description of the result
result, updates = theano.scan(fn=lambda prior_result, A: prior_result * A,
                              outputs_info=T.ones_like(A),
                              non_sequences=A,
                              n_steps=k)

# We only care about A**k, but scan has provided us with A**1 through A**k.
# Discard the values that we don't care about. Scan is smart enough to
# notice this and not waste memory saving them.
final_result = result[-1]

# compiled function that returns A**k
power = theano.function(inputs=[A,k], outputs=final_result, updates=updates)

print(power(range(10),2))
print(power(range(10),4))

结果

[  0.   1.   4.   9.  16.  25.  36.  49.  64.  81.]
[  0.00000000e+00   1.00000000e+00   1.60000000e+01   8.10000000e+01
   2.56000000e+02   6.25000000e+02   1.29600000e+03   2.40100000e+03
   4.09600000e+03   6.56100000e+03]


        上面程序中 fn是一个匿名函数 给定prior_result 和A 返,回 prior_result * A.参数的顺序是固定的,我们可以看到此时由于output不是一个字典,所以我们默认使用上一步的输出(taps=-1),然后才是所有的non_sequences,即prior_result=outputs[-1],A=non_sequences.

        然后我们初始化output为A和一样的大小,和dtype,所有元素的值为1。

         第1步,初始化output=[1,1,1,1,1,1,1,1,1,1]

                      [1,1,1,1,1,1,1,1,1,1]*[0,1,2,3,4,5,6,7,8,9]=[0,1,2,3,4,5,6,7,8,9]

          第2步[0,1,2,3,4,5,6,7,8,9]*[0,1,2,3,4,5,6,7,8,9]=  【0.   1.   4.   9.  16.  25.  36.  49.  64.  81.]



import numpy

coefficients = theano.tensor.vector("coefficients")
x = T.scalar("x")

max_coefficients_supported = 10000

# Generate the components of the polynomial
components, updates = theano.scan(fn=lambda coefficient, power, free_variable: coefficient * (free_variable ** power),
                                  outputs_info=None,
                                  sequences=[coefficients, theano.tensor.arange(max_coefficients_supported)],
                                  non_sequences=x)
# Sum them up
polynomial = components.sum()

# Compile a function
calculate_polynomial = theano.function(inputs=[coefficients, x], outputs=polynomial)

# Test
test_coefficients = numpy.asarray([1, 0, 2], dtype=numpy.float32)
test_value = 3
print(calculate_polynomial(test_coefficients, test_value))
print(1.0 * (3 ** 0) + 0.0 * (3 ** 1) + 2.0 * (3 ** 2))


19.0
19.0


fn   为lambda函数 coefficient * (free_variable ** power)

根据 scan中参数的默认顺序 test_coefficients=[1, 0, 2] 和 是第一个sequences ,arange(max_coefficients_supported)是第二个sequences,test——value=3 是non_sequences


import numpy as np
import theano
import theano.tensor as T

up_to = T.iscalar("up_to")

# define a named function, rather than using lambda
def accumulate_by_adding(arange_val, sum_to_date):
    return sum_to_date + arange_val
seq = T.arange(up_to)

# An unauthorized implicit downcast from the dtype of 'seq', to that of
# 'T.as_tensor_variable(0)' which is of dtype 'int8' by default would occur
# if this instruction were to be used instead of the next one:
# outputs_info = T.as_tensor_variable(0)

outputs_info = T.as_tensor_variable(np.asarray(0, seq.dtype))
scan_result, scan_updates = theano.scan(fn=accumulate_by_adding,
                                        outputs_info=outputs_info,
                                        sequences=seq)
triangular_sequence = theano.function(inputs=[up_to], outputs=scan_result)

# test
some_num = 15
print(triangular_sequence(some_num))
print([n * (n + 1) // 2 for n in range(some_num)])

[  0   1   3   6  10  15  21  28  36  45  55  66  78  91 105]
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105]


fn=accumulate_by_adding

初始化output为T.as_tensor_variable(np.asarray(0, seq.dtype)),即[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

sequences为[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]

默认taps=-1,则传给fn的第一个参数为outputs[-1],第二个参数为sequences



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值