您的位置:首页 > 其它

Theano2.1.18-基础知识之theano的扩展

2015-06-20 08:37 375 查看
来自: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的图),它们由内连接的ApplyVariable 节点组成。 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_shape, i1_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 例子

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)
可以按照如下形式来测试:

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_shape, grad 和 R_op 方法。将下面的代码放入一个文件中,然后用theano-nose

程序来执行该文件。


4. 基本的测试

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

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 参数来禁用该警告。
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)。

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方法,你可以如下来测试:

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 会运行的。

if __name__ == '__main__':
   t = test_DoubleRop("test_double_rop")
   t.setUp()
   t.test_double_rop()
我们建议如果在运行一个文件的时候,最好运行那个文件中所有的测试,这可以通过在测试文件的最后加上如下的代码:

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() 参数,该参数必须有如下的形式:
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 例子

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)
如下进行测试:

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

#!/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加到一个类中:
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 介绍了下面这几个特殊情况:

Scalar/Elemwise/Reduction Ops
SciPy Ops
Sparse Ops
Random ops
OpenMP Ops
Numba Ops

参考资料:

[1]官网:http://deeplearning.net/software/theano/tutorial/extending_theano.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: