# Theano 符号图结构 使用 `Theano`,首先要定义符号变量,然后是利用这写符号变量进行计算,这些符号被称为 **`variables`**,而操作 `+, -, **, sum(), tanh()` 被称为 **`ops`**,一个 `op` 操作接受某些类型的输入,并返回某些类型的输出。 `Theano` 利用这些来构建一个图结构,一个图结构包括: * **`variable`** 节点 * **`op`** 节点 * **`apply`** 节点 其中,`apply` 节点用来表示一个特定的 `op` 作用在一些特定的 `variables` 上,例如: In [1]: ```py import theano import theano.tensor as T x = T.dmatrix('x') y = T.dmatrix('y') z = x + y ``` ```py Using gpu device 0: GeForce GTX 850M ``` 要显示这个图结构可以用 `pydotprint`,先安装 [graphviz](http://www.graphviz.org)。 `Windows` 下: 在环境变量 path 后加上: * path * C:\Program Files (x86)\Graphviz2.38\bin 然后要先安装 `pydot` 包: 如果你的 `pyparsing >= 2.0` ,则将其降为 `1.5.7`,下载并安装 `pydot-1.0.28`。 安装完之后,找到 `pydot.py` 将其中: ```py graph.append( '%s %s {\n' % (self.obj_dict['type'], self.obj_dict['name']) ) ``` 修改为: ```py graph.append( '%s %s {\n' % (self.obj_dict['type'], quote_if_necessary(self.obj_dict['name'])) ) ``` In [2]: ```py theano.printing.pydotprint(z, outfile='apply1.png', var_with_name_simple=True) ``` ```py The output file is available at apply1.png ``` 它的图结构如下: ![图结构1](apply1.png) `z` 的 `owner` 是一个 `apply` 结构,其 `op` 为: In [3]: ```py z.owner.op.name ``` Out[3]: ```py 'Elemwise{add,no_inplace}' ``` 这个 `apply` 结构的输入值有两个,输出值有一个: In [4]: ```py print z.owner.nin print z.owner.nout ``` ```py 2 1 ``` 查看它的输入: In [5]: ```py z.owner.inputs ``` Out[5]: ```py [x, y] ``` 我们可以用 pprint 来显示它: In [6]: ```py print theano.printing.pprint(z) ``` ```py (x + y) ``` 用 `debugprint` 显示图结构: In [7]: ```py theano.printing.debugprint(z) ``` ```py Elemwise{add,no_inplace} [@A] '' |x [@B] |y [@C] ``` 再看另一个稍微复杂的例子: In [8]: ```py y = x * 2 ``` 查看 `y` 的图谱: In [9]: ```py theano.printing.debugprint(y) ``` ```py Elemwise{mul,no_inplace} [@A] '' |x [@B] |DimShuffle{x,x} [@C] '' |TensorConstant{2} [@D] ``` 这里我们看到,`y` 对应的第二个 `input` 并不是 `2`,而是一个 `DimShuffle` 的操作: In [10]: ```py y.owner.inputs[1].owner.op ``` Out[10]: ```py ``` 它的输入才是常数 2: In [11]: ```py y.owner.inputs[1].owner.inputs ``` Out[11]: ```py [TensorConstant{2}] ``` In [12]: ```py theano.printing.pydotprint(y, outfile='apply2.png', var_with_name_simple=True) ``` ```py The output file is available at apply2.png ``` 其图结构为 ![结构2](apply2.png) ## function 对图的优化 In [13]: ```py a = T.dscalar('a') b = a + a ** 10 f = theano.function([a], b) ``` In [14]: ```py theano.printing.pydotprint(b, outfile='apply_no_opti.png', var_with_name_simple=True) theano.printing.pydotprint(f, outfile='apply_opti.png', var_with_name_simple=True) ``` ```py The output file is available at apply_no_opti.png The output file is available at apply_opti.png ``` 比较一下 `function` 函数对图结构进行的优化: 未优化前: ![没有优化](apply_no_opti.png) 优化后: ![优化](apply_opti.png) ## 图结构的作用 * 计算按照图结构来计算 * 优化,求导