Before you begin
Follow the setup guide for the language you choose: Python, Go, Rust, or C++. CoolBox describes this deep-learning library as an educational implementation for simple neural-network applications; it is not a GPU training framework.
1. Make the XOR examples
Each input has two binary features. XOR returns 1 when exactly one feature is 1, and 0 when both values match. The documented API represents each sample as a Tensor with shape [1, features].
from ml_core import deep_learning as dl
inputs = [
dl.Tensor([1, 2], [0.0, 0.0]),
dl.Tensor([1, 2], [0.0, 1.0]),
dl.Tensor([1, 2], [1.0, 0.0]),
dl.Tensor([1, 2], [1.0, 1.0]),
]
targets = [
dl.Tensor([1, 1], [0.0]),
dl.Tensor([1, 1], [1.0]),
dl.Tensor([1, 1], [1.0]),
dl.Tensor([1, 1], [0.0]),
]
values := [][]float64{{0, 0}, {0, 1}, {1, 0}, {1, 1}}
targetValues := []float64{0, 1, 1, 0}
inputs := make([]*coolbox.Tensor, len(values))
targets := make([]*coolbox.Tensor, len(values))
for i, value := range values {
var err error
inputs[i], err = coolbox.NewTensorFromData([]int{1, 2}, value)
if err != nil { log.Fatal(err) }
defer inputs[i].Close()
targets[i], err = coolbox.NewTensorFromData(
[]int{1, 1}, []float64{targetValues[i]},
)
if err != nil { log.Fatal(err) }
defer targets[i].Close()
}
let inputs = vec![
Tensor::new(&[1, 2], Some(&[0.0, 0.0]))?,
Tensor::new(&[1, 2], Some(&[0.0, 1.0]))?,
Tensor::new(&[1, 2], Some(&[1.0, 0.0]))?,
Tensor::new(&[1, 2], Some(&[1.0, 1.0]))?,
];
let targets = vec![
Tensor::new(&[1, 1], Some(&[0.0]))?,
Tensor::new(&[1, 1], Some(&[1.0]))?,
Tensor::new(&[1, 1], Some(&[1.0]))?,
Tensor::new(&[1, 1], Some(&[0.0]))?,
];
using namespace ml::deep_learning;
const std::vector<Tensor> inputs{
Tensor({1, 2}, std::vector<double>{0.0, 0.0}),
Tensor({1, 2}, std::vector<double>{0.0, 1.0}),
Tensor({1, 2}, std::vector<double>{1.0, 0.0}),
Tensor({1, 2}, std::vector<double>{1.0, 1.0}),
};
const std::vector<Tensor> targets{
Tensor({1, 1}, std::vector<double>{0.0}),
Tensor({1, 1}, std::vector<double>{1.0}),
Tensor({1, 1}, std::vector<double>{1.0}),
Tensor({1, 1}, std::vector<double>{0.0}),
};
2. Build the network
Connect a dense hidden layer and ReLU activation to a one-unit output layer with a sigmoid activation. Use mean squared error as the loss, matching the repository’s Python example.
from ml_core import deep_learning as dl
network = dl.NeuralNetwork()
network.add_layer(dl.DenseLayer(2, 4))
network.add_layer(dl.ReLULayer())
network.add_layer(dl.DenseLayer(4, 1))
network.add_layer(dl.SigmoidLayer())
network.set_loss(dl.MSELoss())
network, err := coolbox.NewNeuralNetwork()
if err != nil { log.Fatal(err) }
defer network.Close()
dense1, err := coolbox.NewDenseLayer(2, 4)
if err != nil { log.Fatal(err) }
defer dense1.Close()
relu, err := coolbox.NewReLULayer()
if err != nil { log.Fatal(err) }
defer relu.Close()
dense2, err := coolbox.NewDenseLayer(4, 1)
if err != nil { log.Fatal(err) }
defer dense2.Close()
sigmoid, err := coolbox.NewSigmoidLayer()
if err != nil { log.Fatal(err) }
defer sigmoid.Close()
for _, layer := range []*coolbox.Layer{dense1, relu, dense2, sigmoid} {
if err := network.AddLayer(layer); err != nil { log.Fatal(err) }
}
loss, err := coolbox.NewLoss(coolbox.MeanSquaredError)
if err != nil { log.Fatal(err) }
defer loss.Close()
if err := network.SetLoss(loss); err != nil { log.Fatal(err) }
let dense1 = Layer::new(LayerKind::Dense { input: 2, output: 4 })?;
let relu = Layer::new(LayerKind::Relu)?;
let dense2 = Layer::new(LayerKind::Dense { input: 4, output: 1 })?;
let sigmoid = Layer::new(LayerKind::Sigmoid)?;
let loss = Loss::new(LossKind::MeanSquaredError)?;
let mut network = NeuralNetwork::new()?;
for layer in [&dense1, &relu, &dense2, &sigmoid] {
network.add_layer(layer)?;
}
network.set_loss(&loss)?;
using namespace ml::deep_learning;
NeuralNetwork network;
network.add_layer(std::make_shared<DenseLayer>(2, 4));
network.add_layer(std::make_shared<ReLULayer>());
network.add_layer(std::make_shared<DenseLayer>(4, 1));
network.add_layer(std::make_shared<SigmoidLayer>());
network.set_loss(std::make_shared<MSELoss>());
3. Train and predict
Train on the four samples, then pass one input into predict. The predicted value should move toward the corresponding target as training converges; exact results can vary with initialization.
Choose a language to see a complete CoolBox-backed XOR example. The API is available in all four languages shown here; use the matching installation guide before compiling or running it.
from ml_core import deep_learning as dl
inputs = [
dl.Tensor([1, 2], [0.0, 0.0]),
dl.Tensor([1, 2], [0.0, 1.0]),
dl.Tensor([1, 2], [1.0, 0.0]),
dl.Tensor([1, 2], [1.0, 1.0]),
]
targets = [
dl.Tensor([1, 1], [0.0]),
dl.Tensor([1, 1], [1.0]),
dl.Tensor([1, 1], [1.0]),
dl.Tensor([1, 1], [0.0]),
]
network = dl.NeuralNetwork()
network.add_layer(dl.DenseLayer(2, 4))
network.add_layer(dl.ReLULayer())
network.add_layer(dl.DenseLayer(4, 1))
network.add_layer(dl.SigmoidLayer())
network.set_loss(dl.MSELoss())
network.train(inputs, targets, epochs=1000, batch_size=4)
prediction = network.predict(inputs[1])
print("Prediction for [0, 1]:", prediction.data()[0])
package main
import (
"fmt"
"log"
coolbox "github.com/MeanderingAI/CoolBox/_deliverables/libraries/bindings/go_bindings"
)
func main() {
inputs := make([]*coolbox.Tensor, 4)
values := [][]float64{{0, 0}, {0, 1}, {1, 0}, {1, 1}}
targetValues := []float64{0, 1, 1, 0}
targets := make([]*coolbox.Tensor, 4)
for i := range values {
var err error
inputs[i], err = coolbox.NewTensorFromData([]int{1, 2}, values[i])
if err != nil { log.Fatal(err) }
defer inputs[i].Close()
targets[i], err = coolbox.NewTensorFromData([]int{1, 1}, []float64{targetValues[i]})
if err != nil { log.Fatal(err) }
defer targets[i].Close()
}
network, err := coolbox.NewNeuralNetwork()
if err != nil { log.Fatal(err) }
defer network.Close()
dense1, err := coolbox.NewDenseLayer(2, 4)
if err != nil { log.Fatal(err) }
defer dense1.Close()
relu, err := coolbox.NewReLULayer()
if err != nil { log.Fatal(err) }
defer relu.Close()
dense2, err := coolbox.NewDenseLayer(4, 1)
if err != nil { log.Fatal(err) }
defer dense2.Close()
sigmoid, err := coolbox.NewSigmoidLayer()
if err != nil { log.Fatal(err) }
defer sigmoid.Close()
for _, layer := range []*coolbox.Layer{dense1, relu, dense2, sigmoid} {
if err := network.AddLayer(layer); err != nil { log.Fatal(err) }
}
loss, err := coolbox.NewLoss(coolbox.MeanSquaredError)
if err != nil { log.Fatal(err) }
defer loss.Close()
if err := network.SetLoss(loss); err != nil { log.Fatal(err) }
if err := network.Train(inputs, targets, 1000, 4, false); err != nil { log.Fatal(err) }
prediction, err := network.Predict(inputs[1])
if err != nil { log.Fatal(err) }
defer prediction.Close()
result, err := prediction.Values()
if err != nil { log.Fatal(err) }
fmt.Println("Prediction for [0, 1]:", result[0])
}
use coolbox_rs::{Layer, LayerKind, Loss, LossKind, NeuralNetwork, Tensor};
fn main() -> Result<(), String> {
let inputs = vec![
Tensor::new(&[1, 2], Some(&[0.0, 0.0]))?,
Tensor::new(&[1, 2], Some(&[0.0, 1.0]))?,
Tensor::new(&[1, 2], Some(&[1.0, 0.0]))?,
Tensor::new(&[1, 2], Some(&[1.0, 1.0]))?,
];
let targets = vec![
Tensor::new(&[1, 1], Some(&[0.0]))?,
Tensor::new(&[1, 1], Some(&[1.0]))?,
Tensor::new(&[1, 1], Some(&[1.0]))?,
Tensor::new(&[1, 1], Some(&[0.0]))?,
];
let dense1 = Layer::new(LayerKind::Dense { input: 2, output: 4 })?;
let relu = Layer::new(LayerKind::Relu)?;
let dense2 = Layer::new(LayerKind::Dense { input: 4, output: 1 })?;
let sigmoid = Layer::new(LayerKind::Sigmoid)?;
let loss = Loss::new(LossKind::MeanSquaredError)?;
let mut network = NeuralNetwork::new()?;
for layer in [&dense1, &relu, &dense2, &sigmoid] {
network.add_layer(layer)?;
}
network.set_loss(&loss)?;
network.train(&inputs, &targets, 1000, 4, false)?;
let prediction = network.predict(&inputs[1])?;
println!("Prediction for [0, 1]: {:?}", prediction.data()?);
Ok(())
}
#include <iostream>
#include <memory>
#include <vector>
#include "ml/deep_learning/neural_network.h"
int main() {
using namespace ml::deep_learning;
const std::vector<Tensor> inputs{
Tensor({1, 2}, std::vector<double>{0.0, 0.0}),
Tensor({1, 2}, std::vector<double>{0.0, 1.0}),
Tensor({1, 2}, std::vector<double>{1.0, 0.0}),
Tensor({1, 2}, std::vector<double>{1.0, 1.0}),
};
const std::vector<Tensor> targets{
Tensor({1, 1}, std::vector<double>{0.0}),
Tensor({1, 1}, std::vector<double>{1.0}),
Tensor({1, 1}, std::vector<double>{1.0}),
Tensor({1, 1}, std::vector<double>{0.0}),
};
NeuralNetwork network;
network.add_layer(std::make_shared<DenseLayer>(2, 4));
network.add_layer(std::make_shared<ReLULayer>());
network.add_layer(std::make_shared<DenseLayer>(4, 1));
network.add_layer(std::make_shared<SigmoidLayer>());
network.set_loss(std::make_shared<MSELoss>());
network.train(inputs, targets, 1000, 4, false);
const auto prediction = network.predict(inputs[1]);
std::cout << "Prediction for [0, 1]: "
<< prediction.data().at(0) << '\n';
}
What to try next
Try the documented Adam optimizer or the multiclass example linked in the deep-learning guide . For the full feature list and current limitations, consult that guide before adapting it to a larger problem.