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

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 与其右乘,表达式即: .

可选的布尔 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()  

九、文档

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

时间: 2024-11-03 21:47:05

Theano2.1.18-基础知识之theano的扩展的相关文章

Theano2.1.21-基础知识之theano中多核的支持

来自:http://deeplearning.net/software/theano/tutorial/multi_cores.html Multi cores support in Theano 一.BLAS 操作 BLAS是一个针对于某些数学上操作的接口,其中包括两个向量.一个向量和一个矩阵.两个矩阵(即,介于向量/矩阵和矩阵/矩阵之间的点积操作).当然有许多这样接口的不同的实现方法,有些还是可以并行的. Theano是想尽可能使用这个接口来保证整体的性能.所以如果想要实现theano的并行

第二节,基础知识之更多的例子

先声明:theano模块的内容大都是参考来源于网上,并亲手实践复现一遍,也有部分内容是自己补充 本文会列出所参考文章,如有版权问题,请联系我,我会及时删除 # -*- coding: utf-8 -*- """ Created on Fri Mar 23 16:53:19 2018 @author: zy """ ''' Theano2.1.3-基础知识之更多的例子 http://www.cnblogs.com/shouhuxianjian/p/

linux入门基础知识及简单命令介绍

linux入门基础知识介绍 1.计算机硬件组成介绍 计算机主要由cpu(运算器.控制器),内存,I/O,外部存储等构成. cpu主要是用来对二进制数据进行运算操作,它从内存中取出数据,然后进行相应的运算操作.不能从硬盘中直接取数据. 内存从外部存储中取出数据供cpu运存.内存的最小单位是字节(byte) 备注:由于32的cpu逻辑寻址能力最大为32内存单元.因此32位cpu可以访问的最大内存空间为:4GB,算法如下: 2^32=2^10*2^10*2^10*2^2 =1024*1024*1024

Keepalived基础知识

大纲: 一.什么是Keepalived? 二.VRRP协议简介. 三.Keepalived原理. 四.Keepalived配置文件详解. 五.Keepalived配置示例. 一.什么是Keepalived? 什么是Keepalived呢,keepalived观其名可知,保持存活,在网络里面就是保持在线了,也就是所谓的高可用或热备,用来防止单点故障(单点故障是指一旦某一点出现故障就会导致整个系统架构的不可用)的发生,那说到keepalived时不得不说的一个协议就是VRRP协议,可以说这个协议就是

javascript的基础知识及面向对象和原型属性

自己总结一下javascript的基础知识,希望对大家有用,也希望大家来拍砖,毕竟是个人的理解啊 1.1 类型检查:typeof(验证数据类型是:string) var num = 123; console.log(typeof num); // 1.2 in 运算符 作用:判断指定属性是否存在于指定的对象中. 如果指定的属性存在于指定的对象中,则 in 运算符会返回 true. 语法: 属性 in 对象 返回值:true 或者 false 示例: var obj = { age: 18 };

Linux基础知识题解答(五)

题目来自老男孩BLOG:http://oldboy.blog.51cto.com/2561410/1709569,比较适合新手,空余的时候做一下,可以巩固Linux基础知识,有不对的地方欢迎指正. (1)155729 -rw-r--r--.  1 root root   35 Oct 28 2011  oldboy 请解析上面的每一列内容 文件inode号,文件访问权限,硬链接数,文件所属用户,文件所属组,文件最后修改时间,文件名 (2)描述下硬链接和软连接的区别 1.硬链接原文件/链接文件共用

IP地址基础知识

IP地址基础知识 网络号:用于识别主机所在的网络:主机号:用于识别该网络中的主机. 一 OSI/RM模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 二 TCP/IP模型 数据链路层(网络接口层):Wi-Fi(IEEE 802.11) · WiMAX(IEEE 802.16) ·ATM · DTM · 令牌环 · 以太网 ·FDDI · 帧中继 · GPRS · EVDO ·HSPA · HDLC · PPP · L2TP ·PPTP · ISDN·STP 等 网络层协议(互联网

美国绿卡基础知识:I-539和I-129表格的应用回复新帖

美国绿卡基础知识:I-539和I-129表格的应用 发布于: 2011/07/25  8:43 am 引用 I-539,就是和万金油类似的表格.不管你是要延期,还是转换身份:不管你是 B-2 到 F-1,还是 H-1 到 F-2,通通都是它.它唯一不能做的就是,转到 H-1 去,或 H-1 的延期及换雇主.那是 I-129 的职责.来到美国之后,没有填过 I-539 表格的同学,恐怕是凤毛麟角.谁没有改过身份?F-2 改成 F-1 去读书,H-1 被 laid off 了 就 变成 H-4. 还

struct结构体基础知识

/* ============================================================================ Name : TestStruct.c Author : lf Version : Copyright : Your copyright notice Description : struct结构体基础知识 ==================================================================