Scala Guide


We hereby introduce a new set of Keras-Style API based on Keras 1.2.2 in BigDL for the sake of user-friendliness. Users, especially those familiar with Keras, are recommended to use the new API to create a BigDL model and train, evaluate or tune it in a distributed fashion.

To define a model in Scala using the Keras-Style API, now one just need to import the following packages:


One of the highlighted features with regard to the new API is shape inference. Users only need to specify the input shape (a Shape object excluding batch dimension, for example, inputShape=Shape(3, 4) for 3D input) for the first layer of a model and for the remaining layers, the input dimension will be automatically inferred.


Input and output shapes of a model in the Keras-Style API are described by the Shape object in Scala, which can be classified into SingleShape and MultiShape.

SingleShape is just a list of Int indicating shape dimensions while MultiShape is essentially a list of Shape.

Example code to create a shape:

// create a SingleShape
val shape1 = Shape(3, 4)
// create a MultiShape consisting of two SingleShape
val shape2 = Shape(List(Shape(1, 2, 3), Shape(4, 5, 6)))

You can use method toSingle() to cast a Shape to a SingleShape. Similarly, use toMulti() to cast a Shape to a MultiShape.

Define a model

You can define a model either using Sequential API or Functional API. Remember to specify the input shape for the first layer.

After creating a model, you can call the following methods:


See here on how to train, predict or evaluate a defined model.

Sequential API

The model is described as a linear stack of layers in the Sequential API. Layers can be added into the Sequential container one by one and the order of the layers in the model will be the same as the insertion order.

To create a sequential container:


Example code to create a sequential model:

import{Sequential, Dense, Activation}

val model = Sequential[Float]()
model.add(Dense(32, inputShape = Shape(128)))

Functional API

The model is described as a graph in the Functional API. It is more convenient than the Sequential API when defining some complex model (for example, a model with multiple outputs).

To create an input node:

Input(inputShape = null, name = null)


To create a graph container:

Model(input, output)


To merge a list of input nodes (NOT layers), following some merge mode in the Functional API:


merge(inputs, mode = "sum", concatAxis = -1) // This will return an output NODE.


Example code to create a graph model:

import{Input, Dense, Model}

// instantiate input nodes
val input1 = Input[Float](inputShape = Shape(8))
val input2 = Input[Float](inputShape = Shape(6))
// call inputs() with an input node and get an output node
val dense1 = Dense[Float](10).inputs(input1)
val dense2 = Dense[Float](10).inputs(input2)
// merge two nodes following some merge mode
val output = merge(inputs = List(dense1, dense2), mode = "sum")
// create a graph container
val model = Model[Float](Array(input1, input2), output)


See here for all the available layers for the new set of Keras-Style API.

To set the name of a layer, call the method setName(name) of the layer.

LeNet Example

Here we adopt our Keras-Style API to define a LeNet CNN model to be trained on the MNIST dataset:


val model = Sequential()
model.add(Reshape(Array(1, 28, 28), inputShape = Shape(28, 28, 1)))
model.add(Convolution2D(6, 5, 5, activation = "tanh").setName("conv1_5x5"))
model.add(Convolution2D(12, 5, 5, activation = "tanh").setName("conv2_5x5"))
model.add(Dense(100, activation = "tanh").setName("fc1"))
model.add(Dense(10, activation = "softmax").setName("fc2"))

model.getInputShape().toSingle().toArray // Array(-1, 28, 28, 1)
model.getOutputShape().toSingle().toArray // Array(-1, 10)

See here for detailed introduction of LeNet, the full example code and running instructions.