‹ Back to Tutorials

The neural network class

NeuralNetwork owns the model layers, their connections, input/output metadata, trainable parameters and persistent state. It supports sequential models, residual connections and general multi-input graphs on CPU or CUDA.

Most projects should start with one of OpenNN’s ready-made network classes. Build directly with NeuralNetwork when a custom graph is required.

Contents:

  1. Choose a network type
  2. Construct a standard network
  3. Inspect layers and dimensions
  4. Configure layers
  5. Build a custom graph
  6. Select device and precision
  7. Run inference
  8. Save and load a model

1. Choose a network type

The maintained ready-made models build a valid layer graph and assign the corresponding NetworkTask:

  • ApproximationNetwork for regression and function approximation.
  • ClassificationNetwork for binary and multiclass tabular classification.
  • ForecastingNetwork and ForecastingLstmNetwork for time series.
  • AutoAssociationNetwork for reconstruction and anomaly detection.
  • ImageClassificationNetwork, ResNet and YoloNetwork for vision.
  • TextClassificationNetwork, Transformer, TextGenerationNetwork, Qwen3, Bert and BertForSequenceClassification for language.

The old model-type constructor and the former perceptron/probabilistic layers are no longer part of the current API. Fully connected hidden and output stages are represented by Dense layers with the required activation function.

2. Construct a standard network

The three shapes passed to a tabular network describe its inputs, hidden layers and outputs. For an Iris classifier with four inputs, two hidden layers and three classes:

ClassificationNetwork neural_network(
    Shape{4},
    Shape{8, 4},
    Shape{3});

ClassificationNetwork adds a scaling layer, the requested dense hidden layers and a final dense output. Binary classification uses Sigmoid; multiclass classification uses Softmax. Approximation networks add unscaling and clamping stages around a linear output.

When dimensions come from a data set, use feature counts rather than source-column counts:

const Index inputs_number =
    dataset.get_features_number("Input");
const Index targets_number =
    dataset.get_features_number("Target");

ClassificationNetwork neural_network(
    {inputs_number},
    {8, 4},
    {targets_number});

3. Inspect layers and dimensions

The network exposes its graph, shapes, labels and parameter count without exposing ownership of its layers:

const NetworkTask task = neural_network.get_task();
const Shape input_shape = neural_network.get_input_shape();
const Shape output_shape = neural_network.get_output_shape();

const Index layers_number =
    neural_network.get_layers_number();
const Index parameters_number =
    neural_network.get_parameters_number();

const vector<string> labels =
    neural_network.get_layer_labels();
const vector<vector<Index>>& sources =
    neural_network.get_source_layers();

Retrieve a layer by label, type or position. get_first returns the first matching layer, while get_layer accesses a specific label or index.

Layer* first_dense =
    neural_network.get_first("Dense");

const auto& output_layer =
    neural_network.get_layer("classification_layer");

4. Configure layers

Cast only after checking the layer type. The following example changes the first dense layer and activates dropout:

auto* dense = dynamic_cast<opennn::Dense*>(
    neural_network.get_first("Dense"));

if(dense)
{
    dense->set_activation_function("ReLU");
    dense->set_batch_normalization(true);
    dense->set_dropout_rate(0.1f);
}

Other current layer families include scaling/unscaling, clamping, activation, recurrent and LSTM, convolution, pooling, normalization, embedding, tokenizer, multi-head attention, grouped-query attention, concatenation, addition, upsampling and detection layers.

Input and output variable metadata are used by reporting, expression export and response optimization:

neural_network.set_input_names(
    {"sepal_length", "sepal_width",
     "petal_length", "petal_width"});

neural_network.set_output_names(
    {"setosa", "versicolor", "virginica"});

5. Build a custom graph

add_layer transfers ownership of a layer to the network. With no explicit sources, a layer consumes the preceding layer; the first layer consumes the network input.

NeuralNetwork custom_network;
custom_network.set_task(NetworkTask::Approximation);

custom_network.add_layer(
    make_unique<Scaling>(Shape{4}));
custom_network.add_layer(
    make_unique<opennn::Dense>(Shape{4}, Shape{8}, "ReLU"));
custom_network.add_layer(
    make_unique<opennn::Dense>(Shape{8}, Shape{1}, "Identity"));
custom_network.add_layer(
    make_unique<Unscaling>(Shape{1}));
custom_network.add_layer(
    make_unique<Clamping>(Shape{1}));

custom_network.set_input_variables(vector<Variable>(4));
custom_network.set_output_variables(vector<Variable>(1));
custom_network.compile();

For residual or multi-input graphs, pass source-layer indices as the second argument to add_layer. Addition and Concatenation combine multiple sources after their shapes have been validated.

6. Select device and precision

Set the global configuration before constructing or compiling the network:

Configuration::instance().set(
    Device::CUDA,
    Type::BF16);

ClassificationNetwork neural_network(
    {inputs_number},
    {32, 16},
    {targets_number});

Supported devices are CPU, CUDA and Auto. Supported numeric modes are FP32, BF16, INT8 and Auto. Training uses FP32 or BF16; INT8 is an inference-storage path.

A network keeps the configuration resolved when it is compiled. If the global configuration changes later, construct a new network or call compile again deliberately.

7. Run inference

calculate_outputs accepts matrices for tabular batches and rank-3/rank-4 tensors for sequence and image inputs:

MatrixR inputs(1, 4);
inputs << 5.1f, 3.5f, 1.4f, 0.2f;

const MatrixR outputs =
    neural_network.calculate_outputs(inputs);

The scaling, unscaling, activation and clamping layers are part of inference. Supply values in the original input units unless the calling path explicitly uses pre-scaled tensors.

8. Save and load a model

JSON stores the complete graph, metadata, parameters and states. Binary files are also available for parameters and recurrent state:

neural_network.save("iris_model.json");
neural_network.save_parameters_binary(
    "iris_parameters.bin");

NeuralNetwork restored_network("iris_model.json");

For standalone deployment, use ModelExpression to export C, embedded C, Python, JavaScript or PHP source.

References

Continue with the training strategy class tutorial.