> For the complete documentation index, see [llms.txt](https://wiki.brain4j.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.brain4j.org/quickstart/neural-network-example.md).

# Neural Network Example

In this quickstart you will train your first neural network with Brain4J. The goal is to learn the XOR logical operator, a classic example that cannot be solved by a linear model and therefore requires a neural network with hidden layers.

## The XOR operation

The XOR function behaves as follows:

| x₁ | x₂ | XOR |
| -- | -- | --- |
| 0  | 0  | 0   |
| 0  | 1  | 1   |
| 1  | 0  | 1   |
| 1  | 1  | 0   |

## Architecture

We start by defining the network architecture. For such a simple problem, even a very small network would be sufficient, but we will use a slightly over-parameterized model for clarity.

```java
ModelSpecs specs = ModelSpecs.of(
    new InputLayer(2),
    new DenseLayer(16, Activations.RELU),
    new DenseLayer(16, Activations.RELU),
    new DenseLayer(1, Activations.SIGMOID)
);
```

The `InputLayer` defines the shape of the input (2 features), the hidden layers use ReLU activations and the output layer uses Sigmoid to map predictions to the range `[0, 1]`.

{% hint style="warning" %}
The first layer must be an `InputLayer`. Omitting it will result in an exception during compilation.
{% endhint %}

Once the architecture is defined, we can compile the model:

```java
Model model = specs.compile(42); // seed set to 42 for reproducibility
model.summary();
```

Calling `summary()` prints the model structure and parameter count to the console.

## Dataset Loading & Creation

Brain4J separates model definition from data handling. Here we build a small in-memory dataset representing the XOR truth table.

```java
public ListDataSource getDataSource() {
    List<Sample> samples = new ArrayList<>();
    
    for (int x = 0; x <= 1; x++) {
        for (int y = 0; y <= 1; y++) {
            Tensor input = Tensors.vector(x, y);
            Tensor label = Tensors.vector(x ^ y);
            
            samples.add(new Sample(input, label));
        }
    }
    
    return new ListDataSource(samples, true, 1);
}
```

The dataset is shuffled and trained with a batch size of 1.

## Training

We configure the training process using binary cross-entropy and the Adam optimizer.

```java
public TrainingConfig getConfig() {
    return new TrainingConfig(
        new BinaryCrossEntropy(),
        new Adam(0.1),
        new StochasticUpdater()
    );
}
```

To monitor training progress, we attach two monitors:

```java
TrainingConfig config = getConfig();
ListDataSource dataset = getDataSource();

List<Monitor> monitors = List.of(
    new DefaultMonitor(), 
    new EvalMonitor(dataset, 25)
);
```

Monitors are used to keep track of the training process.&#x20;

* `DefaultMonitor` prints training progress.
* `EvalMonitor` evaluates the model every 25 epochs.

We can now start training:

```java
Trainer trainer = new Trainer(model, monitors, config);
trainer.fit(dataset, 100);
```

## Evaluating

Once our model finished training, we can evaluate it's results:

```java
EvaluationResult evaluationResult = model.evaluate(dataset, config.loss());
System.out.println(evaluationResult.results());
```

We expect the results to be similar to this:

<figure><img src="https://3611897925-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBx144Adhq5uetdBYheDy%2Fuploads%2FeAUKJ54DgEU5hXhv7CbF%2Fimage.png?alt=media&amp;token=09dc7b6c-a94b-4edb-a78a-48e1fbf06ded" alt=""><figcaption></figcaption></figure>
