Theano2.1.4-基础知识之图结构
来自:http://deeplearning.net/software/theano/tutorial/symbolic_graphs.html
Graph Structures
Theano是将符号数学化的计算表示成graphs。这些graphs是由将Apply 和 Variable节点内连接而组成的,它们是分别与函数的应用和数据相连接的。 操作是由 Op 实例所表示的,而数据类型是由 Type 实例所表示的。下面有一段代码和一个图表,该图表用来说明由这些代码所构建的结构。这些应该有助于你理解如何将这些片拟合到一起:
代码:
x = dmatrix('x')
y = dmatrix('y')
z = x + y
图

箭头用来表示对指向的python对象的引用。这里的蓝色盒子是一个 Apply 节点。红色盒子是 Variable 节点。绿色圆圈是Ops.。紫色盒子是 Types。
在创建 Variables 之后,对它们应用 Apply Ops 从而得到更多的变量,并得到一个二分、有向、无环图。变量指向
Apply 节点的过程是用来表示函数通过它们的owner 域来生成它们 。这些Apply节点是通过它们的inputs和outputs域来得到它们的输入和输出变量的 (Apply 的实例同样包含指向他们outputs的引用的列表,不过这些指针不计算在这个graph内)。
x 和 y 的owner 域的指向都是None是因为它们不是另一个计算的结果。如果它们中的一个是另一个计算的结果,那么owner域将会指向另一个的蓝色盒子比如 z 。
注意到 Apply 实例的输出指向z
,而z.owner也指回Apply实例的。
一、一个显式的例子
在这个例子中,我们将会对比两种定义相同graph的方式。首先,一段短代码用来构建一个表达式 (graph),该正常的方式是大多数graph构建的时候自动使用的。第二种方式,我们将会使用一段较长的代码来干相同的事情,这里面没有用到任何的快捷方式,所以这可以让graph的构建变得很 explicit。
1.1 Short example
这就是通常的方式:
# create 3 Variables with owner = None
x = T.matrix('x')
y = T.matrix('y')
z = T.matrix('z') # create 2 Variables (one for 'e', one intermediate for y*z)
# create 2 Apply instances (one for '+', one for '*')
e = x + y * z
1.2 Long example
这就是显式的构建graph的方式:
from theano.tensor import add, mul, Apply, Variable, TensorType # Instantiate a type that represents a matrix of doubles
float64_matrix = TensorType(dtype = 'float64', # double
broadcastable = (False, False)) # matrix # We make the Variable instances we need.
x = Variable(type = float64_matrix, name = 'x')
y = Variable(type = float64_matrix, name = 'y')
z = Variable(type = float64_matrix, name = 'z') # This is the Variable that we want to symbolically represents y*z
mul_variable = Variable(type = float64_matrix)
assert mul_variable.owner is None # Instantiate a symbolic multiplication
node_mul = Apply(op = mul,
inputs = [y, z],
outputs = [mul_variable])
# Fields 'owner' and 'index' are set by Apply
assert mul_variable.owner is node_mul
# 'index' is the position of mul_variable in mode_mul's outputs
assert mul_variable.index == 0 # This is the Variable that we want to symbolically represents x+(y*z)
add_variable = Variable(type = float64_matrix)
assert add_variable.owner is None # Instantiate a symbolic addition
node_add = Apply(op = add,
inputs = [x, mul_variable],
outputs = [add_variable])
# Fields 'owner' and 'index' are set by Apply
assert add_variable.owner is node_add
assert add_variable.index == 0 e = add_variable # We have access to x, y and z through pointers
assert e.owner.inputs[0] is x
assert e.owner.inputs[1] is mul_variable
assert e.owner.inputs[1].owner.inputs[0] is y
assert e.owner.inputs[1].owner.inputs[1] is z
注意到如何调用 Apply 来修改当 Variables指向的输出是自身的时候的 owner 和 index 域,和如何改变在输出列表中占据的顺序位置。这整个机制建立的一个DAG
(有向无环图,Directed Acyclic Graph),从而来表示计算的过程,graph可以在theano中被编译和优化。
二、自动包装
在graph中所有的节点都必须是 Apply 或者 Result的实例,不过
<Op subclass>.make_node() 通常会包装常量来满足这些约束。例如, tensor.add() 操作实例可以写成如下形式:
e = dscalar('x') + 1
构建如下的graph:
node = Apply(op = add,
inputs = [Variable(type = dscalar, name = 'x'),
Constant(type = lscalar, data = 1)],
outputs = [Variable(type = dscalar)])
e = node.outputs[0]
三、Graph Structures
下面的部分概述了可以用在建立theano计算graph的结构的每个类型。这里介绍这几种结构: Apply, Constant, Op, Variable and Type.
3.1 Apply
一个Apply 节点是一个内部节点的类型,用来表示theano中的 computation
graph 。不同于 Variable nodes,Apply 节点通常不是直接被最终用户操作的。。它们可以通过变量的onwer域来访问。
Apply节点通常是Apply类的一个实例。它表示Op 在一个或多个输入上的应用,这里每个输入都是一个 Variable。按照惯例,每个Op都有责任去了解如何从一个输入列表中构建一个Apply节点。因此,
Apply节点可以从 Op和输入列表的基础上,通过调用 Op.make_node(*inputs)来得到。
相比较于python语言来说, Apply 节点是函数调用的theano版本,而 Op 是函数定义的theano版本。
一个Apply实例有着下面三个很重要的域::
- 3.1.1 op
- Op 决定着在什么地方使用函数/转换。
- 3.1.2 inputs
- Variables 的列表,用来表示函数的参数。
- 3.1.3 outputs
- Variables 的列表,用来表示函数的返回值。
Apply实例可以通过调用 gof.Apply(op, inputs, outputs)来创建。
3.2 Op
theano中的Op 是在某些类型的输入上定义一个具体的计算,并生成某些类型的输出。它等效于在大多数编程语言中的函数定义。从一个输入 Variables 的列表和一个Op,你就可以建立一个 Apply 节点,来表示Op
对输入的应用。
理解一个Op(函数的定义)和Apply节点(函数的应用)之间的差别是很重要的。如果你使用theano的结构来解释python语言,写的代码就像 def f(x): ... ,将会对f
生成一个Op,然而如果像 a = f(x) 或者 g(f(4), 5) 那么就生成一个涉及到f
Op的Apply节点。
3.3 Type
theano中的 Type 用来表示潜在数据对象上的一组约束。这些约束允许theano能够定制C
代码来处理它们,并对计算graph进行静态优化。例如, 在theano.tensor中的irow 类型会在数据上有以下约束:
- 必须是 numpy.ndarray: isinstance(x, numpy.ndarray)的实例
- 必须是32位整数的数组: str(x.dtype) == 'int32'
- shape必须是1xN: len(x.shape) == 2 and x.shape[0] == 1
在知道这些约束条件下,theano可以生成额外的C代码,声明正确的数据类型和基于维度上进行准确次数的循环。
Theano的 Type 不等同于 Python 的type 或者
class。在Theano中, irow 和 dmatrix 都是使用 numpy.ndarray 来作为潜在的类型来进行计算和存储数据,然而他们都是不同的theano
type。使用dmatrix时候的约束如下:
- 必须是 numpy.ndarray: isinstance(x, numpy.ndarray)的实例
- 必须是64位的浮点数数组: str(x.dtype) == 'float64'
- shape必须是 MxN,在 M 或 N上都没有限制: len(x.shape) == 2
这些约束不同于上面列出的irow的约束。
在这些情况中,type可以完全对应于python的type,例如我们这里定义的double 类型,对应着python的float。不过这些不是必须的,除非指定了,所以当我们说“type”的时候,说的就是theano的type。
3.4 Variable
Variable 是当你使用theano的时候主要用到的数据结构。你操作的符号输入都是变量,而且通过各种Ops在输入上的使用得到的也是变量。例如,当输入下面的命令:
>>> x = theano.tensor.ivector()
>>> y = -x
x 和 y 都是变量,即变量类的实例。x和y
的 Type 都是 theano.tensor.ivector.
y 是计算的输出值对应的变量,而x是对应于输入的变量。计算的自身是通过另一个节点来表示的,一个Apply 节点,和通过 y.owner来进行访问。
更具体的说,theano中一个变量是是一个基本结构,用来表示在计算中某个具体的点上的基准。通常是类 Variable 或者是它的一个子类的实例。
变量 r 包含着4个重要的域:
- 3.4.1 type
- Type 定义这可以在计算中使用的变量。
- 3.4.2 owner
- t是为None 或者一个变量的 Apply 节点的一个输出。
- 3.4.3 index
- 整数,例如 owner.outputs[index] 是 r (当 owner 为
None的时候忽略) - 3.4.4 name
- 一个字符串,用于友好的打印和调试。
变量还有一个特殊的子类: Constant.
3.4.5 Constant
一个常量就是有着一个额外域data的 Variable ,它只能被设置一次。当在计算graph中用作 Opapplication的输入的时候,需要假设该输入总是常量的数据域部分。更进一步的说,需要假设 Op 不会修改该输入,也就是说一个常量是可以参与大量的优化的,比如在C中的常量内联,常量折叠等。
在一个 function的输入列表中,常量是无需指定的。事实上,做的话还会引起一个异常。
四、Graph 结构的扩展
当我们开始对一个theano函数进行编写的时候,我们需要计算一些额外的信息。这部分描述的是所提供的信息的一部分,不是所有都说清楚了,所以如果当你找不到的时候,可以 email theano的开发团队。
该 graph是在编译的开始进行复制。所以在编译的时候修改不会影响到用户的graph。
每个变量都接受的一个新域叫做clients。它是一个对图中使用过的变量的每个位置的引用列表, 。如果length为0,就意味着该变量没有被使用。每个被使用的位置都是通过包含2个元素的元组描述的。下面就是该对的两个类型:
- 第一个元素是一个 Apply节点.
- 第一个元素是字符串“output”,也就是说该函数的输出是这个变量。
在对的这两个类型中,元组的第二个元素是一个索引,例如: var.clients[*][0].inputs[index] orfgraph.outputs[index] 就是这个变量。
import theano
v = theano.tensor.vector()
f = theano.function([v], (v+1).sum())
theano.printing.debugprint(f)
# Sorted list of all nodes in the compiled graph.
topo = f.maker.fgraph.toposort()
topo[0].outputs[0].clients
# [(Sum(Elemwise{add,no_inplace}.0), 0)]
topo[1].outputs[0].clients
# [('output', 0)] # An internal variable
var = topo[0].outputs[0]
client = var.clients[0]
client
# (Sum(Elemwise{add,no_inplace}.0), 0)
type(client[0])
# <class 'theano.gof.graph.Apply'>
assert client[0].inputs[client[1]] is var # An output of the graph
var = topo[1].outputs[0]
client = var.clients[0]
client
# ('output', 0)
assert f.maker.fgraph.outputs[client[1]] is var
参考资料:
[1] 官网:http://deeplearning.net/software/theano/extending/graphstructures.html#type
Theano2.1.4-基础知识之图结构的更多相关文章
- C语言基础知识-程序流程结构
C语言基础知识-程序流程结构 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.概述 C语言支持最基本的三种程序运行结构:顺序结构,选择结构,循环结构. 顺序结构:程序按顺序执行, ...
- C#基础知识之类和结构体
虽然项目中一直在使用类.结构体等类型,仔细琢磨,还真无法系统的说出个所以然.记录一下类.结构体.类和结构体区别 一.类 对于类,大家都特别熟悉.简单的介绍一下类的结构,然后记录一下Class需要注意的 ...
- C#基础知识之类和结构
虽然项目中一直在使用类.结构体等类型,仔细琢磨,还真无法系统的说出个所以然.记录一下类.结构体.类和结构体区别 一.类 对于类,大家都特别熟悉.简单的介绍一下类的结构,然后记录一下Class需要注意的 ...
- Python基础知识2-内置数据结构(下)
bytes.bytearray #思考下面例子: a = 1 b = a print(a == b)#True print(a is b)#True print(id(a) is id(b))#Fal ...
- C语言基础知识【程序结构】
C 程序结构1.C 程序主要包括以下部分:预处理器指令函数变量语句 & 表达式注释2.#include <stdio.h> int main(){ /* 我的第一个 C 程序 ...
- C基础知识(8):结构体、共用体、位域
结构体 数组允许定义可存储相同类型数据项的变量,而结构体是C编程中另一种用户自定义的可用的数据类型,它允许用户可以存储不同类型的数据项. struct 语句的格式如下: struct [structu ...
- Python基础知识(程序结构)
流程控制语句 选择语句.条件表达式.循环语句.跳转语句.pass空语句 程序结构三种基本结构 顺序结构.选择结构.循环结构 顺序结构 按照代码顺序依次运行 选择结构 根据条件表达式结果选择执行不同的语 ...
- Python基础知识4--数据结构(树)
树 树的概念 堂兄弟的双亲不一定是兄弟关系. 二叉树 斜树 满二叉树 完全二叉树 二叉树的性质
- Python基础知识2-内置数据结构(上)
分类 数值型 用浮点型的时候注意别和"=="一起使用. 数字的处理函数 注意round()函数的特殊:四舍六入五取偶 类型判断 列表list 列表list定义 初始化 列表索引访 ...
随机推荐
- linux查看硬件常用命令
最近整理了平时工作中经常使用的命令,主要分为两大块,一块是查看硬件信息的命令,另一块是监控硬件运转情况的命令.这一篇只涉及查看硬件信息的命令,有关监控硬件运转的命令,我会在下一篇博客中给大 ...
- Oracle Latch的学习【原创】
Latch详解 - MaxChou 本文以学习为目的,大部分内容来自网络转载. 什么是Latch 串行化 数据库系统本身是一个多用户并发处理系统,在同一个时间点上,可能会有多个用户同时操作数据库.多个 ...
- 0014 Java学习笔记-集合-HashMap集合
主要的方法 + 构造方法: * HashMap(); - 默认大小16,负载因子0.75 * HashMap(int initialCapacity); * HashMap(int initialCa ...
- Ineedle驱动方式dpdk测试性能
这次主要是测试在dpdk方案下,ineedle的处理包的性能. 发包工具: 使用立永当时写的一个发包工具:linux_pcap 做法:大概是从网上抓取了一些数据包,将源ip替换为随即ip,sip替换为 ...
- URL编码知识摘抄备忘
网页工具 http://www.107000.com/T-UrlEncode/ 参考: 维基百科http://zh.wikipedia.org/zh/%E7%99%BE%E5%88%86%E5%8F% ...
- System V IPC(1)-消息队列
一.概述 System V三种IPC:消息队列,信号量,共享内存.这三种IPC最先出现在AT&am ...
- 学习OpenStack之(5):在Mac上部署Juno版本OpenStack 四节点环境
0. 前沿 经过一段时间的折腾,终于在自己的Mac上装好了Juno版本的四节点环境.这过程中,花了大量的时间,碰到了许多问题,学到不少知识,折腾过不少其实不需要折腾的东西,本文试着来对这过程做个总结. ...
- c语言结构体小知识
引自:http://c.biancheng.net/cpp/html/88.html 结构体在内存中是连续存储的 struct stu{ char *name; //姓名 int num; //学号 ...
- LCIS(最长公共上升子序列)Vijos1264神秘的咒语
描述 身为拜月教的高级间谍,你的任务总是逼迫你出生入死.比如这一次,拜月教主就派你跟踪赵灵儿一行,潜入试炼窟底. 据说试炼窟底藏着五行法术的最高法术:风神,雷神,雪妖,火神,山神的咒语.为了习得这些法 ...
- Teredo 是一项 IPv6/IPv4 转换技术
Teredo 是一项 IPv6/IPv4 转换技术,能够实现在处于单个或者多个 IPv4 NAT 后的主机之间的 IPv6 自动隧道.来自 Teredo 主机的 IPv6 数据流能够通过 NAT,因 ...