Using Sequential API


BigDL supports two different model definition styles: Sequential API and Functional API.

Here we introduce how to define a model in Sequential API.


Define a simple model

Suppose we want to define a model with three layers

Linear -> Sigmoid -> Softmax

You can write code like this

Scala:

val model = Sequential()
model.add(Linear(...))
model.add(Sigmoid())
model.add(Softmax())

Python:

model = Sequential()
model.add(Linear(...))
model.add(Sigmoid())
model.add(Softmax())

In the above code, we first create a container Sequential. Then add the layers into the container one by one. The order of the layers in the model is same with the insertion order. This model definition looks very straightforward.

BigDL provides multiple types of contianers allow user to define complex model in sequential style. We will take a look at it.


Define a model with branches

Suppose we want to define a model like this

Linear -> ReLU --> Linear -> ReLU
               |-> Linear -> ReLU

The model has two outputs from two branches. The inputs of the branches are both the output from the first ReLU.

You can define the model like this

Scala

val branch1 = Sequential().add(Linear(...)).add(ReLU())
val branch2 = Sequential().add(Linear(...)).add(ReLU())
val branches = ConcatTable().add(branch1).add(branch2)

val model = Sequential()
model.add(Linear(...))
model.add(ReLU())
model.add(branches)

Python

branch1 = Sequential().add(Linear(...)).add(ReLU())
branch2 = Sequential().add(Linear(...)).add(ReLU())
branches = ConcatTable().add(branch1).add(branch2)

val model = Sequential()
model.add(Linear(...))
model.add(ReLU())
model.add(branches)

In the above code, to handle the branch structure, we use another container ConcatTable. When you add layers into ConcatTable, the new layer won't be placed after the previous one but will become a new branch.

The input of the model is a tensor and the output of the model is two tensors.


Define a model with merged branch

Suppose we want to define a model like this

Linear -> ReLU --> Linear -> ReLU ----> Add
               |-> Linear -> ReLU --|

In the model, the outputs of the two branches are merged by an add operation.

You can define the model like this

Scala

val branch1 = Sequential().add(Linear(...)).add(ReLU())
val branch2 = Sequential().add(Linear(...)).add(ReLU())
val branches = ConcatTable().add(branch1).add(branch2)

val model = Sequential()
model.add(Linear(...))
model.add(ReLU())
model.add(branches)
model.add(CAddTable())

Python

branch1 = Sequential().add(Linear(...)).add(ReLU())
branch2 = Sequential().add(Linear(...)).add(ReLU())
branches = ConcatTable().add(branch1).add(branch2)

val model = Sequential()
model.add(Linear(...))
model.add(ReLU())
model.add(branches)
model.add(CAddTable())

To merge the outputs of the branches by an add operation, we use CAddTable. It takes a list of tensors from the previous layer, and merge the tensors by adding them together.

BigDL provides many merge layers. Please check Merge layers document page. They all take a list of tensors as input and merge the tensors by some operation.


Define a model with multiple inputs

We have already seen how to define branches in model and how to merge branches. What if we have multiple input? Suppose we want to define a model like this

Linear -> ReLU ----> Add
Linear -> ReLU --|

The above model takes two tensors as input, and merge them together by add operation.

You can define the model like this

Scala

val model = Sequential()
val branches = ParallelTable()
val branch1 = Sequential().add(Linear(...)).add(ReLU())
val branch2 = Sequential().add(Linear(...)).add(ReLU())
branches.add(branch1).add(branch2)
model.add(branches).add(CAddTable())

Python

model = Sequential()
branches = ParallelTable()
branch1 = Sequential().add(Linear(...)).add(ReLU())
branch2 = Sequential().add(Linear(...)).add(ReLU())
branches.add(branch1).add(branch2)
model.add(branches).add(CAddTable())

In the above code, we use ParallelTable to handle the multiple inputs. ParallelTable also define a multiple branches structure like ConcatTable. The difference is it takes a list of tensors as inputs and assign each tensor to the corresponding branch.