graph_survey.md 6.6 KB
Newer Older
Q
qijun 已提交
1 2
## Survey on Graph

Q
qijun 已提交
3
Neural network framework often provides symbolic API for users to write network topology conveniently. This doc manily focus on symbolic API in most popular neural network frameworks, and try to find out how to parse symbolic configuration to a portable file, such as protobuf or json.
Q
qijun 已提交
4 5 6

### Mxnet

Q
qijun 已提交
7
The core concept of symbolic API is `Symbol`. Mxnet implements `Symbol` class in C++, and export to Python using C-API. Please refer to the comments in Mxnet:
Q
qijun 已提交
8

Q
qijun 已提交
9 10 11 12 13

`Symbol` is help class used to represent the operator node in Graph.
`Symbol` acts as an interface for building graphs from different components like Variable, Functor and Group. `Symbol` is also exported to python front-end (while Graph is not) to enable quick test and deployment. Conceptually, symbol is the final operation of a graph and thus including all the information required (the graph) to evaluate its output value.


Q
qijun 已提交
14
A simple network topology wrote by Symbol is as follows:
Q
qijun 已提交
15 16 17 18

```python
def get_symbol(num_classes=10, **kwargs):
    data = mx.symbol.Variable('data')
Q
qijun 已提交
19
    data = mx.symbol.Flatten(data=data)
Q
qijun 已提交
20 21 22 23 24 25 26 27 28 29 30
    fc1  = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128)
    act1 = mx.symbol.Activation(data = fc1, name='relu1', act_type="relu")
    fc2  = mx.symbol.FullyConnected(data = act1, name = 'fc2', num_hidden = 64)
    act2 = mx.symbol.Activation(data = fc2, name='relu2', act_type="relu")
    fc3  = mx.symbol.FullyConnected(data = act2, name='fc3', num_hidden=num_classes)
    mlp  = mx.symbol.SoftmaxOutput(data = fc3, name = 'softmax')
    return mlp
```



Q
qijun 已提交
31 32 33 34 35 36 37
Varible here is actually a Symbol. Every basic Symbol will correspond to one Node, and every Node has its own NodeAttr. There is a op field in NodeAttr class, when a Symbol represents Variable(often input data), the op field is null.

Symbol contains a data member, std::vector<NodeEntry> outputs, and NodeEntry cantains a poniter to Node. We can follow the Node pointer to get all the Graph.

And Symbol can be saved to a Json file.

Here is a detailed example:
Q
qijun 已提交
38

Q
qijun 已提交
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
```
>>> import mxnet as mx
>>> data = mx.symbol.Variable('data')
>>> print data.debug_str()
Variable:data

>>> data = mx.symbol.Flatten(data=data)
>>> print data.debug_str()
Symbol Outputs:
	output[0]=flatten0(0)
Variable:data
--------------------
Op:Flatten, Name=flatten0
Inputs:
	arg[0]=data(0) version=0
Q
qijun 已提交
54

Q
qijun 已提交
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
>>> fc1  = mx.symbol.FullyConnected(data = data, name='fc1', num_hidden=128)
>>> print fc1.debug_str()
Symbol Outputs:
	output[0]=fc1(0)
Variable:data
--------------------
Op:Flatten, Name=flatten0
Inputs:
	arg[0]=data(0) version=0
Variable:fc1_weight
Variable:fc1_bias
--------------------
Op:FullyConnected, Name=fc1
Inputs:
	arg[0]=flatten0(0)
	arg[1]=fc1_weight(0) version=0
	arg[2]=fc1_bias(0) version=0
Attrs:
	num_hidden=128
Q
qijun 已提交
74

Q
qijun 已提交
75
```
Q
qijun 已提交
76 77 78 79 80


### TensorFlow


Q
qijun 已提交
81
The core concept of symbolic API is `Tensor`. Tensorflow defines `Tensor` in Python. Please refer to the comments in TensorFlow:
Q
qijun 已提交
82

Q
qijun 已提交
83
A `Tensor` is a symbolic handle to one of the outputs of an `Operation`. It does not hold the values of that operation's output, but instead provides a means of computing those values in a TensorFlow [Session](https://www.tensorflow.org/api_docs/python/tf/Session).
Q
qijun 已提交
84

Q
qijun 已提交
85
A simple example is as follows:
Q
qijun 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

```python
  # Build a dataflow graph.
  c = tf.constant([[1.0, 2.0], [3.0, 4.0]])
  d = tf.constant([[1.0, 1.0], [0.0, 1.0]])
  e = tf.matmul(c, d)

  # Construct a `Session` to execute the graph.
  sess = tf.Session()

  # Execute the graph and store the value that `e` represents in `result`.
  result = sess.run(e)
```

  
Q
qijun 已提交
101 102 103
The main method of `Tensor` is as follows: 
 
 
Q
qijun 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
```python
@property
def op(self):
  """The `Operation` that produces this tensor as an output."""
  return self._op

@property
def dtype(self):
   """The `DType` of elements in this tensor."""
  return self._dtype

@property
def graph(self):
  """The `Graph` that contains this tensor."""
  return self._op.graph

@property
def name(self):
  """The string name of this tensor."""
  if not self._op.name:
    raise ValueError("Operation was not named: %s" % self._op)
  return "%s:%d" % (self._op.name, self._value_index)

@property
def device(self):
  """The name of the device on which this tensor will be produced, or None."""
  return self._op.device
```


Q
qijun 已提交
134
Tensor can be taken as target to run by session. Tensor contains all the information of Graph, and tracks data dependency.
Q
qijun 已提交
135 136


Q
qijun 已提交
137
Here is a detailed example:
Q
qijun 已提交
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152


```
>>> import tensorflow as tf
>>> c = tf.constant([[1.0, 2.0], [3.0, 4.0]])
>>> print c.graph
<tensorflow.python.framework.ops.Graph object at 0x10f256d50>
>>> d = tf.constant([[1.0, 1.0], [0.0, 1.0]])
>>> print d.graph
<tensorflow.python.framework.ops.Graph object at 0x10f256d50>
>>> e = tf.matmul(c, d)
>>> print e.graph
<tensorflow.python.framework.ops.Graph object at 0x10f256d50>
```

Q
qijun 已提交
153 154 155
### Dynet


Q
qijun 已提交
156
The core concept of symbolic API is `Expression`, and Dynet defines `Expression` class in C++.
Q
qijun 已提交
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171


A simple example is as follows:

```cpp
ComputationGraph cg;
Expression W = parameter(cg, pW);

Expression in = input(cg, xs[i]);
Expression label = input(cg, ys[i]);
Expression pred = W * in;
Expression loss = square(pred - label);
```

The input data and parameter are also represented by Expression. Every basci Expression corresponds to a Node. And input data is also a Node. 
Q
qijun 已提交
172

Q
qijun 已提交
173
Expression has a data member ComputationGraph, and ComputationGraph will be modified in users' configuring process. Expression can be a running target, beacuse Expression contains all dependency.
Q
qijun 已提交
174 175


Q
qijun 已提交
176 177 178
Here is a detailed example:

write topology in C++
Q
qijun 已提交
179 180 181 182 183 184 185 186 187 188 189 190 191

```
ComputationGraph cg;
Expression W = parameter(cg, pW);
cg.print_graphviz();

Expression pred = W * xs[i];
cg.print_graphviz();

Expression loss = square(pred - ys[i]);
cg.print_graphviz();
```

Q
qijun 已提交
192
compile and print
Q
qijun 已提交
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223

```
# first print
digraph G {
  rankdir=LR;
  nodesep=.05;
  N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"];
}
# second print
digraph G {
  rankdir=LR;
  nodesep=.05;
  N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"];
  N1 [label="v1 = v0 * -0.98"];
  N0 -> N1;
}
# third print
digraph G {
  rankdir=LR;
  nodesep=.05;
  N0 [label="v0 = parameters({1}) @ 0x7ffe4de00110"];
  N1 [label="v1 = v0 * -0.98"];
  N0 -> N1;
  N2 [label="v2 = -1.88387 - v1"];
  N1 -> N2;
  N3 [label="v3 = -v2"];
  N2 -> N3;
  N4 [label="v4 = square(v3)"];
  N3 -> N4;
}
```
Q
qijun 已提交
224 225 226 227 228 229

### Conclusion


Actually, Symbol/Tensor/Expression in Mxnet/TensorFlow/Dynet are the same level concepts. We use a unified name Expression here, this level concept has following features:

Q
qijun 已提交
230
- Users wirte topoloy with symbolic API, and all return value is Expression, including input data and parameter.
Q
qijun 已提交
231 232
- Expression corresponds with a global Graph, and Expression can also be composed.
- Expression tracks all dependency and can be taken as a run target