zoukankan      html  css  js  c++  java
  • Theano2.1.18-基础知识之theano的扩展

    来自:http://deeplearning.net/software/theano/tutorial/extending_theano.html

    Extending Theano

        该教程覆盖了如何使用新颖的ops来扩展theano。它主要关注哪些能够提供一个python实现的ops。而Extending Theano with a C Op 是基于c的op实现。该教程的第一部分介绍了theano的graphs,因为提供一个新颖的theano op需要对theano graphs有个基本的理解。然后在概括的介绍了定义一个op的最重要的方法。

        正如一个图文说明需要的,该教程会介绍如何编写一个简单的基于python的op,该op是基于double上执行的。同样会介绍如何实现测试来确保之前op的工作的有效性。

    note:

    该教程不会介绍如何编写得到输入值的视图或者对其修改的op。所以这里介绍的所有ops必须返回新的分配的内存或者重用由函数perform() 的参数output_storage 所提供的内存。 想了解这些过程可以查阅 Views and inplace operations 。

    如果你的op返回针对输入的视图或者修改,却不是如介绍的那样实现的,那么theano就还是会运行,并且返回某些graphs的正确的值和其他graphs的错误结果。

    强烈建议在DebugMode (Theano flag mode=DebugMode) 下运行你的测试,因为它会验证你的op行为是否正确。

    note:查阅 Developer Start Guide 来了解版本框架的信息,即git 和GitHub,和开发工作流程以及如何进行有质量的贡献。

    一、Theano Graphs

                                                  ../_images/apply_node.png

        Theano会将符号数学化计算表示成graph。这些graph都是二分图 (有2种类型node的图),它们由内连接的Apply 和 Variable 节点组成。 Variable 节点在graph中表示数据,例如:输入、输出或者中间值。所以一个graph的输入和输出也就是theano Variable 节点的列表. Apply 节点通过在这些变量上执行计算来生成新的值。每个 Apply 节点会连接到 Op 的一个实例,从而来表示所执行的计算。该教程详细介绍了如何编写这样一个op实例。关于图结构的更详细信息,查阅: Graph Structures 翻译

     二、Op 结构

           op就是继承自gof.Op的某个python对象。该部分提供了一些方法的概述,可以用来实现一个新的op。。不过没有介绍你可能遇到或者需要的所有可能的情况。不过更详细的可以查阅: Op’s contract.

    import theano
    
    class MyOp(theano.Op):
        # Properties attribute
        __props__ = ()
    
        def make_node(self, *inputs):
            pass
    
        # Python implementation:
        def perform(self, node, inputs_storage, output_storage):
            pass
    
        # Other type of implementation
        # C implementation: [see theano web site for other functions]
        def c_code(...):
            # ...
            pass
        # Other implementations (pycuda, ...):
        def make_thunk(self, node, storage_map, _, _2):
            pass
    
        # optional:
        check_input = True
    
        def __init__(self, ...):
            pass
    
        def grad(self, inputs, g):
            pass
    
        def R_op(self, inputs, eval_points):
            pass
    
        def infer_shape(node, (i0_shapes, ...)):
            pass

    op需要执行在gof.Op接口中定义的一些方法。对于op来说,首先需要定义方法make_node()  然后在实现该方法,例如perform()Op.c_code() 或 make_thunk()

     

    make_node() 方法生成一个Apply节点来表示在提供的输入上op的应用。该方法需要对下面三个事情负责:

    • 首先检查输入变量类型是否与当前的op兼容。如果在当前输入类型上没法应用,那么必须抛出一个异常 (例如 TypeError).
    • 在theano的符号语言中,它会对*inputs上找到的变量进行操作,从而推断出符号输出变量的类型。并创建一个适合的符号类型的输出变量来作为该操作的输出。
    • 它创建一个有着输入和输出变量的apply实例,然后返回该apply实例。

    perform() 方法用来定义一个op的python实现。它有以下几个参数:

    • node 是对一个Apply节点的引用,从前面的 Op‘s make_node() 方法获得。它通常不会用在简单的ops中,不过它包含的符号信息需要复杂的ops。
    • inputs 是对数据的引用列表,会被非符号语句所操作(即,python,Numpy中的语句)。
    • output_storage 是存储单元的列表,其中存储的是输出数据。每一个单元存储着op的一个输出。放入 output_storage 的数据必须匹配符号输出的类型。禁止改变output_storage中的列表的长度。函数模式可以允许output_storage 中的元素在执行过程中保持不变,或者将output_storage单元的值重设为None。而且允许对op所需要用到的一些内存进行预分配。该特性允许 perform 重用调用期间的内存,例如,假设在output_storage中预先分配了一些内存,其中有着正确的dtype,不过shape却是错的,而且存在某些stride模式。

    perform() 方法必须由输入里决定。也就是说,当用在同一个输入的时候,该方法必须返回相同的输出。

    gof.Op 允许使用其他的方法来定义op的实现。例如可以通过定义 Op.c_code() 来提供一个对该op的c实现。查阅 Extending Theano with a C Op 来获得关于 Op.c_code() 和其他相关的c方法更详细的介绍。注意到一个op可以提供c和pythong两种实现。

    make_thunk() 方法是另一个可以用来代替 perform()的方法。它返回一个thunk.。该thunk被定义成一个0参数函数,该函数很好的封装了op在对应节点的参数上的计算过程。该方法有以下几个参数:

    • node 是Apply的实例,其中会请求一个thunk。
    • storage_map 是列表的字典,通过将变量映射成一个元素列表(one-element lists)来处理变量的当前的值。这个一元素列表可以作为指向值的指针,可以与其他节点和实例来共享该”指针“。
    • compute_map 同样也是列表的字典。将变量映射成一元素列表来处理布尔值。如果该值是0,那么这个变量就表示还未计算,该值是无效的。如果该值是1,那么这个变量已经被计算过了,那么是有效的。如果该值是2,那么这个变量是已经被垃圾回收了,不再有效,而且无法被这次调用所请求。返回的函数必须确保计算值在compute_map中计算过。

    make_thunk() 在你自己想要生成代码和编译的时候是很有用的。例如,这可以让你使用PyCUDA来编译GPU代码。

    如果 make_thunk() 被一个op所定义,那么它会被theano所使用来获得该op的实现。 perform() 和 Op.c_code()会被忽略掉。

    其他通过op定义的可选的方法:

     __str__() 方法对你的op提供了一个有意义的字符串表示。

    __eq__() 和 __hash__() 分别定义了两个ops是否相等和计算一个op实例的哈希。它们会在优化阶段被用来融合节点,那些有着相同计算的节点(相同的输入,相同的操作)。两个ops可以通过 __eq__() 来计算是否相等,即在有着相同输入的时候是否有着相同的输出。

     __props__ 列出的属性影响着计算是如何执行的 (通常来说,它们就是你在__init__()中设置的那样). 它必须是一个元组。如果你没有任何属性,那么你应该将这个属性设置成空元组( tuple ())。

    __props__ 能够自动的生成合适的 __eq__() 和 __hash__() 给定从__props__生成的方法 __eq__(), 两个ops如果它们对于__props__中列出的所有属性都有有着相同的值,那么这两个ops就是相等的。给定从__props__ 生成的方法 __hash__() ,两个ops如果对于 __props__中列出的所有属性都有着相同的值,那么这两个ops有着相同的hash。 __props__ 同样会对你的op生成一个合适的 __str__() 。这需要theano的版本为 September 1st, 2014 or version 0.7.

     infer_shape() 方法允许在没有实际计算输出的情况下,推断op输出变量的shape。它可以作为输入 node(一个对Apply节点的引用)和theano符号变量的列表 (i0_shapei1_shape, ...)(op输入变量的shape)。 infer_shape() 返回一个列表,其中每个元素都是一个元组,用来标识一个输出的shape。这在当你只需要输出的shape而无需计算实际的输出的时候是很有用的,例如在优化的时候。

     grad() 方法适用于你想要对一些包含你op的表达式的损失函数进行微分的时候。在这个方法中梯度可以具体的符号化。它有两个参数inputs 和 output_gradients ,这两个都是符号的theano变量的列表,必须被theano符号化语言所操作。该grad方法必须返回一个列表,其中对应每个输入都有一个变量。每个返回的变量表示关于输入的梯度,而该梯度是基于关于每个输出的符号化梯度上计算得到的(个人:这句话估计理解有误)。如果输出不是关于一个输入的微分,那么该方法就会被定义成针对这个输入返回一个NullType类型的变量。同样的,如果你没有对某些输入实现grad计算,你需要返回关于这个输入的一个NullType类型的变量。查阅 grad()来得到更详细的说明。

     R_op() 方法当你想要让 theano.tensor.Rop 和你的op一起工作的时候是需要使用的。该函数实现了op表示的函数的R-操作。假设函数为 f ,输入为 x 。使用R-操作,即计算f 的jacobian然后通过v 与其右乘,表达式即: frac{partial f}{partial x} v.

    可选的布尔 check_input 属性用来指定你是否想要在你的op中使用这个类型来在c_code中检查它们的输入。它可以用来加速计算,减少开销(特别是在标量上)和减少生成的c文件的数量。

    三、Op 例子

    1. import theano  
        
      class DoubleOp(theano.Op):  
          __props__ = ()  
        
          def make_node(self, x):  
              # check that the theano version has support for __props__  
              assert hasattr(self, '_props')  
              x = theano.tensor.as_tensor_variable(x)  
              return theano.Apply(self, [x], [x.type()])  
        
          def perform(self, node, inputs, output_storage):  
              x = inputs[0]  
              z = output_storage[0]  
              z[0] = x * 2  
        
          def infer_shape(self, node, i0_shapes):  
              return i0_shapes  
        
          def grad(self, inputs, output_grads):  
              return [output_grads[0] * 2]  
        
          def R_op(self, inputs, eval_points):  
              # R_op can receive None as eval_points.  
              # That mean there is no diferientiable path through that input  
              # If this imply that you cannot compute some outputs,  
              # return None for those.  
              if eval_points[0] is None:  
                  return eval_points  
              return self.grad(inputs, eval_points)   

    可以按照如下形式来测试: 

    1. x = theano.tensor.matrix()  
      f = theano.function([x], DoubleOp()(x))  
      import numpy  
      inp = numpy.random.rand(5, 4)  
      out = f(inp)  
      assert numpy.allclose(inp * 2, out)  
      print inp  
      print out  

     四、如何进行测试

          Theano有很多函数来简化测试。这些可以用来测试 infer_shapegrad 和 R_op 方法。将下面的代码放入一个文件中,然后用theano-nose

    程序来执行该文件。

    4.1 基本的测试

         基本的测试就是通过使用op,然后检查返回的是否正确。如果你检测到一个错误,那么你就需要抛出一个异常。你可以使用关键字assert来自动的抛出一个AssertionError。

    1. from theano.tests import unittest_tools as utt  
      from theano import config  
      class test_Double(utt.InferShapeTester):  
          def setUp(self):  
              super(test_Double, self).setUp()  
              self.op_class = DoubleOp  
              self.op = DoubleOp()  
        
          def test_basic(self):  
              x = theano.tensor.matrix()  
              f = theano.function([x], self.op(x))  
              inp = numpy.asarray(numpy.random.rand(5, 4), dtype=config.floatX)  
              out = f(inp)  
              # Compare the result computed to the expected value.  
              utt.assert_allclose(inp * 2, out)  

        我们调用 utt.assert_allclose(expected_value, value) 来对比NumPy ndarray。这抛出一个有着更多信息的错误消息。同样的,这个默认的容忍可以通过theano flags config.tensor.cmp_sloppy 来改变,其值为0, 1 和 2. 默认的值会有着最严格的比较,而1 和2 就比较不那么严格了。

    4.2 测试infer_shape

         当一个类继承自 InferShapeTester 类,那么就可以通过 self._compile_and_check 来测试op的 infer_shape方法。在当只需要输出的shape而无需计算实际的输出的时侯,用来测试该op在graph中的优化情况。另外,它通过优化后的graph计算得到的shape与实际计算的输出的shape进行对比来检查当前的shape是否正确。      self._compile_and_check 会编译一个theano函数。它会将输入和输出的theano变量的列表作为参数(正如theano.function那样),然后将真实值传递给编译后的函数。 它同样会将op类作为一个参数,来保证在优化后的shape graph中没有实例出现。

        如果有错误,那么该函数抛出一个异常。如果你想要看错误的时候的行为,可以使用一个非正常的 infer_shape.

        在测试的时候,如果在不同的维度上shape的值相同 (例如,一个方阵或者有着shape为 (n, n, n),或(m, n, m)的tensor3 ),那么就没法检测。例如,如果 infer_shape 使用矩阵的 width来作为它的height,那么在方阵的情况下就没法检测是否出错了。这就是为什么 self._compile_and_check 在这种情况下会输出一个警告的原因。如果你的操作只在这种矩阵下工作,那么就可以通过 warn=False 参数来禁用该警告。

    1. from theano.tests import unittest_tools as utt  
      from theano import config  
      class test_Double(utt.InferShapeTester):  
          # [...] as previous tests.  
          def test_infer_shape(self):  
              x = theano.tensor.matrix()  
              self._compile_and_check([x],  # theano.function inputs  
                                      [self.op(x)],  # theano.function outputs  
                                      # Always use not square matrix!  
                                      # inputs data  
                                      [numpy.asarray(numpy.random.rand(5, 4),  
                                                     dtype=config.floatX)],  
                                      # Op that should be removed from the graph.  
                                      self.op_class)  

    4.3 测试梯度

        函数 verify_grad 用来验证一个op或者theano graph的梯度。它通过对比分析梯度 (通过符号计算得到的)梯度和数值梯度 (通过有限的微分方法得到的)。

        如果出错了,那么该函数抛出一个异常。如果你想要看出错的情况,你可以执行一个错误的梯度 (例如,移除前面的2)。

     
    1. def test_grad(self):  
          theano.tests.unittest_tools.verify_grad(self.op,  
                                                  [numpy.random.rand(5, 7, 2)])  

    4.4 测试Rop

         类 RopLop_checker 定义了函数RopLop_checker.check_mat_rop_lop()RopLop_checker.check_rop_lop() 和RopLop_checker.check_nondiff_rop(). 这些函数可以用来测试一个具体的op的Rop方法的实现。

    例如,为了验证DoubleOp的Rop方法,你可以如下来测试:

     
    1. import numpy  
      import theano.tests  
      from theano.tests.test_rop import RopLop_checker  
      class test_DoubleRop(RopLop_checker):  
          def setUp(self):  
              super(test_DoubleRop, self).setUp()  
          def test_double_rop(self):  
              self.check_rop_lop(DoubleRop()(self.x), self.in_shape)  
       

    4.5 测试 GPU Ops

        在GPU上执行的Ops应该继承自 theano.sandbox.cuda.GpuOp 而不是 theano.Op。这可以给theano区分它们的机会。目前,我们使用这个在GPU上的和约间代码来测试NVIDIA驱动是否正确工作。

    五、运行你的测试

       为了执行你的测试程序,你需要选择下面的某种方法 :

    5.1 theano-nose

        选择要进行测试的方法就是运行 theano-nose. 在常规的theano安装中,后面的参数会读取操作系统的path,然后直接访问其中的文件夹。而且它也可以在Theano/bin文件夹中被访问。对应于不同的目的,可以使用下面不同的命令: 

    • theano-nose --theano: 运行任何在theano的path上找到的测试。
    • theano-nose folder_name: 运行任何在文件夹folder_name内找到的测试。
    • theano-nose test_file.py: 运行任何在文件test_file.py内的测试。

    下面的命令对于开发者来说特别有用,因为它们可以针对具体的类或者具体的测试被调用

    • theano-nose test_file.py:test_DoubleRop: 运行在类 test_DoubleRop中的测试。
    • theano-nose test_file.py:test_DoubleRop.test_double_op: 只运行在类test_DoubleRop中的测试test_double_op 。

    针对于 theano-nose 的用法和功能的详细介绍,可以使用带有参数为 --help (-h)的命令。(个人:在windows下运行theano-nose会显示找不到该命令,在ubuntu下没问题,即该教程的所有命令其实都是基于linux的,而非windows的。)

    5.2 nosetests

        命令 nosetests 也是很有用的。虽然它缺少和 theano-nose 提供的信息, nosetests 的用法和theano-nose 相似,可以测试任何在python的路径上的文件夹:

    nosetests [suffix similar to the above].

    更多有关 nosetests 的资料,可查阅: nosetests.

    5.3 In-file

       可以增加一块代码在文件的最后,然后运行该文件。在这个例子中,在类test_double_op中的测试 test_DoubleRop 会运行的。

    1. if __name__ == '__main__':  
         t = test_DoubleRop("test_double_rop")  
         t.setUp()  
         t.test_double_rop()  

    我们建议如果在运行一个文件的时候,最好运行那个文件中所有的测试,这可以通过在测试文件的最后加上如下的代码:

    1. if __name__ == '__main__':  
          unittest.main()  

    六、练习

        运行上面的 DoubleOp e例子的代码。

       修改并执行: x * y.

        修改并执行: x + y and x - y.

        你可以省略Rop函数。 试着实现上面的测试过程。

    (注意到当前的theano的逐元素风格的优化只能用在涉及到单一输出的情况下。所以,为了解决这个问题,需要在代码中对这两个操作进行联合的显式优化。)

    七、as_op

        as_op是一个pythong修饰符,用来将一个python函数转换成一个基础theano op,该op会在执行的时候调用所提供的函数。

        不推荐用该方法来建立一个op,不过这却是一个快速实现的方法。

        它有一个可选的 infer_shape() 参数,该参数必须有如下的形式:

    1. def infer_shape(node, input_shapes):  
           # ...  
           return output_shapes  
    • input_shapes 和 output_shapes 是元组列表,用来表示对应的输入/输出的shape。

    note:不提供 infer_shape方法是为了防止对这个op的相关的shape优化 。例如, your_op(inputs, ...).shape 会需要执行该op从而得到shape。

    note:没有grad被定义,也就是不能对包含该op的路径中的函数进行微分。

    note:它将python函数转换成可调用的对象,该对象的输入是已经声明过的theano变量。

     7.1 as_op 例子

     
    1. import theano  
      import numpy  
      from theano.compile.ops import as_op  
        
      def infer_shape_numpy_dot(node, input_shapes):  
          ashp, bshp = input_shapes  
          return [ashp[:-1] + bshp[-1:]]  
       
      @as_op(itypes=[theano.tensor.fmatrix, theano.tensor.fmatrix],  
             otypes=[theano.tensor.fmatrix], infer_shape=infer_shape_numpy_dot)  
      def numpy_dot(a, b):  
         return numpy.dot(a, b)  

    如下进行测试: 

    1. x = theano.tensor.fmatrix()  
      y = theano.tensor.fmatrix()  
      f = function([x, y], numpy_dot(x, y))  
      inp1 = numpy.random.rand(5, 4)  
      inp2 = numpy.random.rand(4, 7)  
      out = f(inp1, inp2)  

    7.2 练习

        运行上的numpy_dot 例子的代码。

        修改并执行: numpy.add 和 numpy.subtract.

        修改并执行: x + y和 x - y.

    八、测试中的随机数

        测试错误可重复在实际中是非常具有说服力的,为了让测试可以重复,就需要得到相同的随机树。你可以通过对Numpy的随机数生成器传入相同的种子来得到。

        更方便的方法就是使用类 InferShapeTester 和 RopLop_checker 。如果你实现了自己的 setUp 函数,别忘了调用其父类的setUp函数。

    更多信息请查阅: Using Random Values in Test Cases.

    答案(Solution 

    1. #!/usr/bin/env python  
      # Theano tutorial  
      # Solution to Exercise in section 'Extending Theano'  
      import unittest  
        
      import theano  
        
        
      # 1. Op returns x * y  
        
      class ProdOp(theano.Op):  
          def __eq__(self, other):  
              return type(self) == type(other)  
        
          def __hash__(self):  
              return hash(type(self))  
        
          def __str__(self):  
              return self.__class__.__name__  
        
          def make_node(self, x, y):  
              x = theano.tensor.as_tensor_variable(x)  
              y = theano.tensor.as_tensor_variable(y)  
              outdim = x.ndim  
              output = (theano.tensor.TensorType  
                        (dtype=theano.scalar.upcast(x.dtype, y.dtype),  
                            broadcastable=[False] * outdim)())  
              return theano.Apply(self, inputs=[x, y], outputs=[output])  
        
          def perform(self, node, inputs, output_storage):  
              x, y = inputs  
              z = output_storage[0]  
              z[0] = x * y  
        
          def infer_shape(self, node, i0_shapes):  
              return [i0_shapes[0]]  
        
          def grad(self, inputs, output_grads):  
              return [output_grads[0] * inputs[1], output_grads[0] * inputs[0]]  
        
        
      # 2. Op returns x + y and x - y  
        
      class SumDiffOp(theano.Op):  
          def __eq__(self, other):  
              return type(self) == type(other)  
        
          def __hash__(self):  
              return hash(type(self))  
        
          def __str__(self):  
              return self.__class__.__name__  
        
          def make_node(self, x, y):  
              x = theano.tensor.as_tensor_variable(x)  
              y = theano.tensor.as_tensor_variable(y)  
              outdim = x.ndim  
              output1 = (theano.tensor.TensorType  
                        (dtype=theano.scalar.upcast(x.dtype, y.dtype),  
                            broadcastable=[False] * outdim)())  
              output2 = (theano.tensor.TensorType  
                        (dtype=theano.scalar.upcast(x.dtype, y.dtype),  
                            broadcastable=[False] * outdim)())  
              return theano.Apply(self, inputs=[x, y], outputs=[output1, output2])  
        
          def perform(self, node, inputs, output_storage):  
              x, y = inputs  
              z1, z2 = output_storage  
              z1[0] = x + y  
              z2[0] = x - y  
        
          def infer_shape(self, node, i0_shapes):  
              return [i0_shapes[0], i0_shapes[0]]  
        
          def grad(self, inputs, output_grads):  
              og1, og2 = output_grads  
              if og1 is None:  
                  og1 = theano.tensor.zeros_like(og2)  
              if og2 is None:  
                  og2 = theano.tensor.zeros_like(og1)  
              return [og1 + og2, og1 - og2]  
        
        
      # 3. Testing apparatus  
        
      import numpy  
      from theano.gof import Op, Apply  
      from theano import tensor, function, printing  
      from theano.tests import unittest_tools as utt  
        
        
      class TestProdOp(utt.InferShapeTester):  
        
          rng = numpy.random.RandomState(43)  
        
          def setUp(self):  
              super(TestProdOp, self).setUp()  
              self.op_class = ProdOp  # case 1  
        
          def test_perform(self):  
              x = theano.tensor.matrix()  
              y = theano.tensor.matrix()  
              f = theano.function([x, y], self.op_class()(x, y))  
              x_val = numpy.random.rand(5, 4)  
              y_val = numpy.random.rand(5, 4)  
              out = f(x_val, y_val)  
              assert numpy.allclose(x_val * y_val, out)  
        
          def test_gradient(self):  
              utt.verify_grad(self.op_class(), [numpy.random.rand(5, 4),  
                                      numpy.random.rand(5, 4)],  
                              n_tests=1, rng=TestProdOp.rng)  
        
          def test_infer_shape(self):  
              x = tensor.dmatrix()  
              y = tensor.dmatrix()  
        
              self._compile_and_check([x, y], [self.op_class()(x, y)],  
                                      [numpy.random.rand(5, 6),  
                                       numpy.random.rand(5, 6)],  
                                      self.op_class)  
        
        
      class TestSumDiffOp(utt.InferShapeTester):  
        
          rng = numpy.random.RandomState(43)  
        
          def setUp(self):  
              super(TestSumDiffOp, self).setUp()  
              self.op_class = SumDiffOp  
        
          def test_perform(self):  
              x = theano.tensor.matrix()  
              y = theano.tensor.matrix()  
              f = theano.function([x, y], self.op_class()(x, y))  
              x_val = numpy.random.rand(5, 4)  
              y_val = numpy.random.rand(5, 4)  
              out = f(x_val, y_val)  
              assert numpy.allclose([x_val + y_val, x_val - y_val], out)  
        
          def test_gradient(self):  
              def output_0(x, y):  
                  return self.op_class()(x, y)[0]  
        
              def output_1(x, y):  
                  return self.op_class()(x, y)[1]  
        
              utt.verify_grad(output_0, [numpy.random.rand(5, 4),  
                                      numpy.random.rand(5, 4)],  
                              n_tests=1, rng=TestSumDiffOp.rng)  
              utt.verify_grad(output_1, [numpy.random.rand(5, 4),  
                                      numpy.random.rand(5, 4)],  
                              n_tests=1, rng=TestSumDiffOp.rng)  
        
          def test_infer_shape(self):  
              x = tensor.dmatrix()  
              y = tensor.dmatrix()  
        
              # adapt the choice of the next instruction to the op under test  
        
              self._compile_and_check([x, y], self.op_class()(x, y),  
                                      [numpy.random.rand(5, 6),  
                                       numpy.random.rand(5, 6)],  
                                      self.op_class)  
        
        
      # as_op exercice  
      import theano  
      import numpy  
      from theano.compile.ops import as_op  
        
        
      def infer_shape_numpy_dot(node, input_shapes):  
          ashp, bshp = input_shapes  
          return [ashp[:-1] + bshp[-1:]]  
       
       
      @as_op(itypes=[theano.tensor.fmatrix, theano.tensor.fmatrix],  
             otypes=[theano.tensor.fmatrix], infer_shape=infer_shape_numpy_dot)  
      def numpy_add(a, b):  
          return numpy.add(a, b)  
        
        
      def infer_shape_numpy_add_sub(node, input_shapes):  
          ashp, bshp = input_shapes  
          # Both inputs should have that same shape, so we just return one of them.  
          return [ashp[0]]  
       
       
      @as_op(itypes=[theano.tensor.fmatrix, theano.tensor.fmatrix],  
             otypes=[theano.tensor.fmatrix], infer_shape=infer_shape_numpy_add_sub)  
      def numpy_add(a, b):  
          return numpy.add(a, b)  
       
       
      @as_op(itypes=[theano.tensor.fmatrix, theano.tensor.fmatrix],  
             otypes=[theano.tensor.fmatrix], infer_shape=infer_shape_numpy_add_sub)  
      def numpy_sub(a, b):  
          return numpy.sub(a, b)  
        
        
      if __name__ == "__main__":  
          unittest.main()  
      View Code

    九、文档

    Documentation Documentation AKA Meta-Documentation中更详细的介绍了如何生成文档。

    下面这个例子介绍如何将docstring加到一个类中: 

    1. import theano  
        
      class DoubleOp(theano.Op):  
      """ Double each element of a tensor. 
       
      :param x: input tensor. 
       
      :return: a tensor of the same shape and dtype as the input with all 
          values doubled. 
       
      :note: 
          this is a test note 
       
      :seealso: 
          You can use the elemwise op to replace this example. 
          Just execute `x * 2` with x being a Theano variable. 
       
      .. versionadded:: 0.6 
      """  
    下面就是在库文档中的说明形式:
    class theano.misc.doubleop.DoubleOp(use_c_code='/usr/bin/g++')

    Double each element of a tensor.

    Parameters: x – input tensor.
    Returns: a tensor of the same shape and dtype as the input with all values doubled.
    Note : this is a test note
    Seealso : You can use the elemwise op to replace this example. Just execute x * 2 with x being a Theano variable.
     

    在0.6版本中新加入的特性。

    十、最后的笔记

        这部分更深的讨论可以查阅高级教程: Extending Theano.

     Other ops 介绍了下面这几个特殊情况:

    参考资料:

    [1]官网:http://deeplearning.net/software/theano/tutorial/extending_theano.html

  • 相关阅读:
    Django通用视图执行过程
    Django HTTP处理流程(自我总结)
    CentOS 安装MySQL5.7
    Python--定时给Ta讲笑话
    【转】对Django框架架构和Request/Response处理流程的分析
    Python模块发布
    Django中使用CKEditor代码高亮显示插件Code Snippet
    页面中的"返回顶部"(位置固定,指定位置显示/隐藏) Label:博客园美化
    跨域请求配置 Amazon AWS S3 腾讯云 阿里云 COS OSS 文件桶解决方案以及推荐 Label:Research
    文件分发服务器 AWS CloudFront(CDN)使用入门-以S3为例 Label:Research
  • 原文地址:https://www.cnblogs.com/shouhuxianjian/p/4594532.html
Copyright © 2011-2022 走看看