1---
2layout: page_api
3title: Symbol API
4permalink: /api/scala/docs/tutorials/symbol
5is_tutorial: true
6tag: scala
7---
8<!--- Licensed to the Apache Software Foundation (ASF) under one -->
9<!--- or more contributor license agreements.  See the NOTICE file -->
10<!--- distributed with this work for additional information -->
11<!--- regarding copyright ownership.  The ASF licenses this file -->
12<!--- to you under the Apache License, Version 2.0 (the -->
13<!--- "License"); you may not use this file except in compliance -->
14<!--- with the License.  You may obtain a copy of the License at -->
15
16<!---   http://www.apache.org/licenses/LICENSE-2.0 -->
17
18<!--- Unless required by applicable law or agreed to in writing, -->
19<!--- software distributed under the License is distributed on an -->
20<!--- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -->
21<!--- KIND, either express or implied.  See the License for the -->
22<!--- specific language governing permissions and limitations -->
23<!--- under the License. -->
24
25# MXNet Scala Symbolic API
26
27Topics:
28
29* [How to Compose Symbols](#how-to-compose-symbols) introduces operator overloading of symbols.
30* [Symbol Attributes](#symbol-attributes) describes how to attach attributes to symbols.
31* [Serialization](#serialization) explains how to save and load symbols.
32* [Executing Symbols](#executing-symbols) explains how to evaluate the symbols with data.
33* [Execution API Reference]({{'/api/scala/docs/api/#org.apache.mxnet.Executor'|relative_url}}) documents the execution APIs.
34* [Multiple Outputs](#multiple-outputs) explains how to configure multiple outputs.
35* [Symbol Creation API Reference]({{'/api/scala/docs/api/#org.apache.mxnet.Symbol'|relative_url}}) documents functions.
36
37We also highly encourage you to read [Symbolic Configuration and Execution in Pictures](symbol_in_pictures).
38
39## How to Compose Symbols
40
41The symbolic API provides a way to configure computation graphs.
42You can configure the graphs either at the level of neural network layer operations or as fine-grained operations.
43
44The following example configures a two-layer neural network.
45
46```scala
47    import org.apache.mxnet._
48    val data = Symbol.Variable("data")
49    val fc1 = Symbol.api.FullyConnected(Some(data), num_hidden = 128, name = "fc1")
50    val act1 = Symbol.api.Activation(Some(fc1), "relu", "relu1")
51    val fc2 = Symbol.api.FullyConnected(Some(act1), num_hidden = 64, name = "fc2")
52    val net = Symbol.api.SoftmaxOutput(Some(fc2), name = "out")
53    :type net
54    // org.apache.mxnet.Symbol
55```
56
57The basic arithmetic operators (plus, minus, div, multiplication) are overloaded for
58*element-wise operations* of symbols.
59
60The following example creates a computation graph that adds two inputs together.
61
62```scala
63    import org.apache.mxnet._
64    val a = Symbol.Variable("a")
65    val b = Symbol.Variable("b")
66    val c = a + b
67```
68
69## Symbol Attributes
70
71You can add an attribute to a symbol by providing an attribute dictionary when you create a symbol.
72
73```scala
74    val data = Symbol.Variable("data", Map("mood"-> "angry"))
75    val op = Symbol.api.Convolution(Some(data), kernel = Shape(1, 1), num_filter = 1, attr = Map("mood" -> "so so"))
76```
77For proper communication with the C++ backend, both the key and values of the attribute dictionary should be strings. To retrieve the attributes, use `attr(key)`:
78
79```
80    data.attr("mood")
81    // Option[String] = Some(angry)
82```
83
84To attach attributes, you can use ```AttrScope```. ```AttrScope``` automatically adds the specified attributes to all of the symbols created within that scope. The user can also inherit this object to change naming behavior. For example:
85
86```scala
87    val (data, gdata) =
88    AttrScope(Map("group" -> "4", "data" -> "great")).withScope {
89      val data = Symbol.Variable("data", attr = Map("dtype" -> "data", "group" -> "1"))
90      val gdata = Symbol.Variable("data2")
91      (data, gdata)
92    }
93    assert(gdata.attr("group").get === "4")
94    assert(data.attr("group").get === "1")
95
96    val exceedScopeData = Symbol.Variable("data3")
97    assert(exceedScopeData.attr("group") === None, "No group attr in global attr scope")
98```
99
100## Serialization
101
102There are two ways to save and load the symbols. You can use the `mxnet.Symbol.save` and `mxnet.Symbol.load` functions to serialize the ```Symbol``` objects.
103The advantage of using `save` and `load` functions is that it is language agnostic and cloud friendly.
104The symbol is saved in JSON format. You can also get a JSON string directly using `mxnet.Symbol.toJson`.
105Refer to [API documentation]({{'/api/scala/docs/api/#org.apache.mxnet.Symbol'|relative_url}}) for more details.
106
107The following example shows how to save a symbol to an S3 bucket, load it back, and compare two symbols using a JSON string.
108
109```scala
110    import org.apache.mxnet._
111    val a = Symbol.Variable("a")
112    val b = Symbol.Variable("b")
113    val c = a + b
114    c.save("s3://my-bucket/symbol-c.json")
115    val c2 = Symbol.load("s3://my-bucket/symbol-c.json")
116    c.toJson == c2.toJson
117    // Boolean = true
118```
119
120## Executing Symbols
121
122After you have assembled a set of symbols into a computation graph, the MXNet engine can evaluate them.
123If you are training a neural network, this is typically
124handled by the high-level [Model class](model) and the [`fit()`] function.
125
126For neural networks used in "feed-forward", "prediction", or "inference" mode (all terms for the same
127thing: running a trained network), the input arguments are the
128input data, and the weights of the neural network that were learned during training.
129
130To manually execute a set of symbols, you need to create an [`Executor`] object,
131which is typically constructed by calling the [`simpleBind(<parameters>)`] method on a symbol.
132
133## Multiple Outputs
134
135To group the symbols together, use the [mxnet.symbol.Group](#mxnet.symbol.Group) function.
136
137```scala
138    import org.apache.mxnet._
139    val data = Symbol.Variable("data")
140    val fc1 = Symbol.api.FullyConnected(Some(data), num_hidden = 128, name = "fc1")
141    val act1 = Symbol.api.Activation(Some(fc1), "relu", "relu1")
142    val fc2 = Symbol.api.FullyConnected(Some(act1), num_hidden = 64, name = "fc2")
143    val net = Symbol.api.SoftmaxOutput(Some(fc2), name = "out")
144    val group = Symbol.Group(fc1, net)
145    group.listOutputs()
146    // IndexedSeq[String] = ArrayBuffer(fc1_output, out_output)
147```
148
149After you get the ```group```, you can bind on ```group``` instead.
150The resulting executor will have two outputs, one for fc1_output and one for softmax_output.
151
152## Next Steps
153* See [IO Data Loading API](io) for parsing and loading data.
154* See [NDArray API](ndarray) for vector/matrix/tensor operations.
155* See [KVStore API](kvstore) for multi-GPU and multi-host distributed training.
156