mirror of
https://github.com/apachecn/ailearning.git
synced 2026-02-11 14:26:04 +08:00
256 lines
3.6 KiB
Markdown
256 lines
3.6 KiB
Markdown
# 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
|
||
|
||
```
|
||
|
||
它的图结构如下:
|
||
|
||

|
||
|
||
`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
|
||
<theano.tensor.elemwise.DimShuffle at 0x1b816390>
|
||
```
|
||
|
||
它的输入才是常数 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
|
||
|
||
```
|
||
|
||
其图结构为 
|
||
|
||
## 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` 函数对图结构进行的优化:
|
||
|
||
未优化前:
|
||
|
||

|
||
|
||
优化后:
|
||
|
||

|
||
|
||
## 图结构的作用
|
||
|
||
* 计算按照图结构来计算
|
||
* 优化,求导 |