# Symbolic and Automatic Differentiation

NDArray is the basic computation unit in MXNet. MXNet also provides a
symbolic interface, named Symbol, to simplify constructing neural networks. Symbol combines flexibility and efficiency. It is similar to
the network configuration in [Caffe](http://caffe.berkeleyvision.org/) and
[CXXNet](https://github.com/dmlc/cxxnet) and the symbols define
the computation graph as in [Theano](http://deeplearning.net/software/theano/).

## Basic Composition of Symbols

The following code creates a two-layer perceptron network:

 ```python
    >>> import mxnet as mx
    >>> net = mx.symbol.Variable('data')
    >>> net = mx.symbol.FullyConnected(data=net, name='fc1', num_hidden=128)
    >>> net = mx.symbol.Activation(data=net, name='relu1', act_type="relu")
    >>> net = mx.symbol.FullyConnected(data=net, name='fc2', num_hidden=64)
    >>> net = mx.symbol.SoftmaxOutput(data=net, name='out')
    >>> type(net)
    <class 'mxnet.symbol.Symbol'>
 ```

Each symbol takes a (unique) string name. *Variable* often defines the inputs,
or free variables. Other symbols take a symbol as their input (*data*),
and might accept other hyperparameters, such as the number of hidden neurons (*num_hidden*)
or the activation type (*act_type*).

The symbol can be seen simply as a function taking several arguments whose
names are automatically generated and can be got with the following:

 ```python
    >>> net.list_arguments()
    ['data', 'fc1_weight', 'fc1_bias', 'fc2_weight', 'fc2_bias', 'out_label']
 ```

 These arguments are the parameters needed by each symbol:

- *data*: Input data needed by the variable *data*
- *fc1_weight* and *fc1_bias*: The weight and bias for the first fully connected layer *fc1*
- *fc2_weight* and *fc2_bias*: The weight and bias for the second fully connected layer *fc2*
- *out_label*: The label needed by the loss

We can also specify the automatically generated names explicitly:

 ```python
    >>> net = mx.symbol.Variable('data')
    >>> w = mx.symbol.Variable('myweight')
    >>> net = mx.symbol.FullyConnected(data=net, weight=w, name='fc1', num_hidden=128)
    >>> net.list_arguments()
    ['data', 'myweight', 'fc1_bias']
 ```

## More Complicated Composition

MXNet provides well-optimized symbols for layers 
commonly used in deep learning (see
[src/operator](https://github.com/dmlc/mxnet/tree/master/src/operator)). We can also easily define new operators
in Python.  The following example first performs an element-wise add between two
symbols, then feeds them to the fully connected operator:

 ```python
    >>> lhs = mx.symbol.Variable('data1')
    >>> rhs = mx.symbol.Variable('data2')
    >>> net = mx.symbol.FullyConnected(data=lhs + rhs, name='fc1', num_hidden=128)
    >>> net.list_arguments()
    ['data1', 'data2', 'fc1_weight', 'fc1_bias']
 ```

We can also construct a symbol in a more flexible way than the single
forward composition exemplified in the preceding example:

 ```python
    >>> net = mx.symbol.Variable('data')
    >>> net = mx.symbol.FullyConnected(data=net, name='fc1', num_hidden=128)
    >>> net2 = mx.symbol.Variable('data2')
    >>> net2 = mx.symbol.FullyConnected(data=net2, name='net2', num_hidden=128)
    >>> composed_net = net(data=net2, name='compose')
    >>> composed_net.list_arguments()
    ['data2', 'net2_weight', 'net2_bias', 'fc1_weight', 'fc1_bias']
 ```

In the preceding example, *net* is used as a function to apply to an existing symbol
*net*, and the resulting *composed_net* will replace the original argument *data* with
*net2*.

## Argument Shape Inference

Now we know how to define a symbol. Next, we can infer the shapes of
all of the arguments it needs given the shape of its input data:

 ```python
    >>> net = mx.symbol.Variable('data')
    >>> net = mx.symbol.FullyConnected(data=net, name='fc1', num_hidden=10)
    >>> arg_shape, out_shape, aux_shape = net.infer_shape(data=(100, 100))
    >>> dict(zip(net.list_arguments(), arg_shape))
    {'data': (100, 100), 'fc1_weight': (10, 100), 'fc1_bias': (10,)}
    >>> out_shape
    [(100, 10)]
 ```

We can use this shape inference as an early debugging mechanism to detect
shape inconsistency.

## Bind the Symbols and Run

Now we can bind the free variables of the symbol and perform forward and backward operations.
The ```bind``` function will create a ```Executor``` that can be used to carry out the real computations:

 ```python
    >>> # define computation graphs
    >>> A = mx.symbol.Variable('A')
    >>> B = mx.symbol.Variable('B')
    >>> C = A * B
    >>> a = mx.nd.ones(3) * 4
    >>> b = mx.nd.ones(3) * 2
    >>> # bind the symbol with real arguments
    >>> c_exec = C.bind(ctx=mx.cpu(), args={'A' : a, 'B': b})
    >>> # do forward pass calclation.
    >>> c_exec.forward()
    >>> c_exec.outputs[0].asnumpy()
    [ 8.  8.  8.]
 ```
For neural nets, a more commonly used pattern is ```simple_bind```, which creates all of the argument arrays for you. Then you can call ```forward```, and ```backward``` (if the gradient is needed)
to get the gradient:

 ```python
    >>> # define computation graphs
    >>> net = some symbol
    >>> texec = net.simple_bind(data=input_shape)
    >>> texec.forward()
    >>> texec.backward()
 ```
The [model API](model.md) is a thin wrapper around the symbolic executors to support neural net training.

We strongly encouraged you to read [Symbolic Configuration and Execution in Pictures](symbol_in_pictures.md),
which provides a detailed explanation of the concepts in pictures.

## How Efficient Is the Symbolic API?

In short, it is designed to be very efficient in both memory and runtime.

The major reason for introducing the Symbolic API is to bring the efficient C++
operations in powerful toolkits, such as CXXNet and Caffe, together with the
flexible dynamic NDArray operations. To maximize runtime performance and memory
utilization, all of the memory and computation resources are
allocated statically during the bind operation.

The coarse-grained operators are equivalent to CXXNet layers, which are
extremely efficient.  We also provide fine-grained operators for more flexible
composition. Because we are also performing more in-place memory allocation, MXNet can
be more memory efficient than CXXNet, and achieves the same runtime, with
greater flexibility.

## Next Steps
* [KVStore](kvstore.md)
