NTDLS.Determinet 2.1.0

dotnet add package NTDLS.Determinet --version 2.1.0
                    
NuGet\Install-Package NTDLS.Determinet -Version 2.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="NTDLS.Determinet" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NTDLS.Determinet" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="NTDLS.Determinet" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add NTDLS.Determinet --version 2.1.0
                    
#r "nuget: NTDLS.Determinet, 2.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package NTDLS.Determinet@2.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=NTDLS.Determinet&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=NTDLS.Determinet&version=2.1.0
                    
Install as a Cake Tool

Determinet

📦 Be sure to check out the NuGet package: https://www.nuget.org/packages/NTDLS.Determinet

Determinet is a versatile multilayer perceptron neural network for .NET, designed for ease of use and extendibility. In addition to the library, you'll find a test harness which includes a character recognition trainer, validator and visual testing tool. These provide working examples of training a model as well as generating predictions.

<img width="822" height="468" alt="image" src="https://github.com/user-attachments/assets/da2362b1-73f0-44a6-a169-db525f9c4ab8" />

Features

  • Fully-connected feed-forward networks with any number of hidden layers.
  • 18 built-in activation functions (see below), each with a gradient-checked derivative.
  • Cross-entropy loss for SoftMax outputs (classification), squared-error loss for everything else (regression).
  • SGD or Adam (AdamW) optimization, single-sample or mini-batch training.
  • Optional layer normalization, weight decay and global gradient-norm clipping.
  • Activation-aware weight initialization (He, LeCun or Glorot).
  • Named input/output labels, so you can work with "temperature" and "rain" instead of array indexes.
  • Compact save/load of the whole model, including optimizer state, so training can be resumed exactly.
  • Thread-safe inference: Forward() never modifies the network.
  • Targets .NET 8, 9 and 10.

Installation

dotnet add package NTDLS.Determinet

Quick start

A network that learns XOR, a classic problem a single layer can't solve:

using NTDLS.Determinet;
using NTDLS.Determinet.Types;
using static NTDLS.Determinet.DniParameters;

// 2 inputs -> 8 hidden (Tanh) -> 2 outputs (SoftMax), with a label for each output.
var configuration = new DniConfiguration { LearningRate = 0.01 };
configuration.AddInputLayer(2);
configuration.AddIntermediateLayer(8, DniActivationType.Tanh);
configuration.AddOutputLayer(2, DniActivationType.SoftMax, ["false", "true"]);

var dni = new DniNeuralNetwork(configuration);
dni.Parameters.Set(Network.UseAdamOptimization, true);

// Each sample is (inputs, expected outputs). For classification the expected output is one-hot.
(double[] inputs, double[] expected)[] samples =
[
    ([0, 0], [1, 0]),
    ([0, 1], [0, 1]),
    ([1, 0], [0, 1]),
    ([1, 1], [1, 0]),
];

for (int epoch = 0; epoch < 500; epoch++)
{
    foreach (var (inputs, expected) in samples)
    {
        double loss = dni.Train(inputs, expected);
    }
}

Making predictions

// Raw outputs: for SoftMax these are probabilities that sum to 1.
double[] outputs = dni.Forward([1, 0]);
int index = outputs.IndexOfMaxValue(out double confidence);   // 1, ~0.99

// Or use the output labels.
dni.Forward([1, 0], out var labels);
var best = labels.Max();
Console.WriteLine($"{best.Key} ({best.Value:n2})");         // true (0.99)

Saving and loading

dni.SaveToFile("xor.dni");

var loaded = DniNeuralNetwork.LoadFromFile("xor.dni");

The file includes the weights, the layer configuration, all parameters and the optimizer state, so a loaded model can be used for predictions or trained further right where it left off.

Mini-batch training

Train() updates the weights after every sample. TrainBatch() averages the gradient over several samples and applies a single update, which gives smoother, less noisy training:

foreach (var batch in samples.Chunk(32))
{
    double averageLoss = dni.TrainBatch(batch);
}

Regression

For predicting real numbers, use an Identity output layer. The network is then trained with squared-error loss:

var configuration = new DniConfiguration { LearningRate = 0.01 };
configuration.AddInputLayer(1);
configuration.AddIntermediateLayer(16, DniActivationType.Tanh);
configuration.AddOutputLayer(1, DniActivationType.Identity);

var dni = new DniNeuralNetwork(configuration);
dni.Parameters.Set(Network.UseAdamOptimization, true);

for (int epoch = 0; epoch < 2000; epoch++)
{
    for (double x = -3; x <= 3; x += 0.25)
    {
        dni.Train([x], [Math.Sin(x)]);
    }
}

double y = dni.Forward([1.0])[0];   // approximately sin(1)

Named inputs

Give the input layer labels and you can supply values by name. Missing names are treated as 0.

var configuration = new DniConfiguration();
configuration.AddInputLayer(2, ["temperature", "humidity"]);
configuration.AddIntermediateLayer(8, DniActivationType.ReLU);
configuration.AddOutputLayer(2, DniActivationType.SoftMax, ["dry", "rain"]);

var dni = new DniNeuralNetwork(configuration);

var input = new DniNamedLabelValues();
input.Set("temperature", 0.7);
input.Set("humidity", 0.9);

dni.Forward(input, out var prediction);
Console.WriteLine(prediction.Max().Key);

Parameters

Network and layer behavior is controlled through named parameters.

// Network-wide settings.
dni.Parameters.Set(Network.LearningRate, 0.001);
dni.Parameters.Set(Network.UseAdamOptimization, true);
dni.Parameters.Set(Network.WeightDecay, 0.01);
dni.Parameters.Set(Network.GradientClip, 5.0);

// Per-layer settings are passed when the layer is added.
var hiddenParams = new DniNamedParameterCollection();
hiddenParams.Set(LeakyReLU.Alpha, 0.05);
hiddenParams.Set(Layer.UseLayerNorm, true);
configuration.AddIntermediateLayer(32, DniActivationType.LeakyReLU, hiddenParams);

// You can also store your own values in the model; they are saved with it.
dni.Parameters.Set("Epochs", 12);
int epochs = dni.Parameters.Get<int>("Epochs");
Parameter Default Description
Network.LearningRate 0.005 Step size of each update. Adam typically wants a smaller value (e.g. 0.0001–0.001) than SGD.
Network.UseAdamOptimization false Use Adam (with decoupled weight decay) instead of plain SGD.
Network.WeightDecay 0.0001 Shrinks weights toward zero to reduce overfitting. With Adam, values around 0.01 are typical.
Network.GradientClip 5.0 Maximum overall size of a single update's gradient. 0 disables clipping.
Network.ComputedLoss — Set by Train()/TrainBatch() to the most recent loss.
Layer.UseLayerNorm false Normalizes a hidden layer's values before its activation function. Can help deeper networks train.
SoftMax.Temperature 1.0 Values above 1 soften the output probabilities, below 1 sharpen them.
LeakyReLU.Alpha 0.01 Slope for negative inputs.
ELU.Alpha 1.0 Scale of the negative region.
SELU.Alpha, SELU.Lambda paper Self-normalizing constants from the SELU paper.
Linear.Alpha, Linear.Range 1, [-1, 1] Slope, and the range the output is clamped to.
Piecewise.Alpha, Piecewise.Range 1, [-1, 1] Slope used outside the range; inside the range the slope is 1.

Built-in Activation Functions

Activation Type What It Does When To Use It Where To Use It
Identity Passes values through unchanged. The neuron is basically “transparent.” Use for pure regression or as a linear output layer when predicting real numbers — e.g., predicting house prices, speed, or temperature. Output
PiecewiseLinear Slope 1 inside a range and a different slope (Alpha) outside it, with no jumps at the edges. Use when you want bounded but mostly linear responses — e.g., controlling actuator strength, image intensity normalization, or testing stable transitions. Hidden (sometimes Output for bounded regression)
Linear Scales input by a slope and optionally clamps to a range. Great for controlled continuous outputs where scaling matters — e.g., steering angle, torque output, or color channel prediction. Output (regression), Hidden (feature scaling)
ReLU (Rectified Linear Unit) Keeps positive values, zeros out negatives. Very fast and stable. The default for most deep learning tasks. Ideal for vision models, embeddings, and dense MLPs — e.g., image recognition, feature extraction, signal processing. Hidden
Sigmoid Squashes output between 0 and 1 (probability curve). Use for binary classification (“yes/no,” “on/off,” “spam/not spam”) or when modeling probability per neuron in multi-label tasks. Output (binary classification), Hidden (gating in LSTMs or attention)
Tanh Squashes output between -1 and 1, centered around 0. Use when values can be positive or negative and symmetry matters — e.g., RNNs, control systems, or directional outputs (-1 left, +1 right). Hidden
LeakyReLU Like ReLU, but negative values leak through slightly instead of being zeroed. Use in deep MLPs to avoid “dead neurons” and keep gradients flowing — especially in dense or deep architectures. Hidden
SoftMax Converts outputs into a probability distribution that sums to 1. Use for multi-class classification — e.g., recognizing characters, digits, objects, or anything where exactly one class is correct. Output only
SimpleSoftMax A simplified SoftMax (no temperature scaling). Use when you need fast, stable classification and temperature tuning isn’t required. Works the same for most classification tasks. Output only
ELU (Exponential Linear Unit) Works like ReLU for positive inputs but smoothly bends for negatives instead of dropping to zero. Use when you want ReLU-like behavior but prefer smoother gradients and mean activations closer to zero — e.g., deep networks prone to “dead neurons.” Hidden
Gaussian (RBF) Outputs a bell curve centered around zero (f(x) = e<sup>-x²</sup>). Use for radial basis networks, feature clustering, or anomaly detection where proximity to a center value matters. Hidden
HardSigmoid A linear, fast approximation of the sigmoid function. Use in lightweight models or embedded systems where performance matters, or when full sigmoid precision isn’t required. Hidden, Output (binary)
HardTanh Like Tanh but clipped to the range [-1, 1] using straight lines. Use when you need bounded outputs but want faster computation — e.g., control tasks, quantized models, or when smoothness isn’t critical. Hidden
Mish Smoothly blends ReLU and Swish behavior (f(x) = x·tanh(ln(1+eˣ))). Use when you want smoother gradients and slightly better generalization in deep MLPs or CNNs — can outperform ReLU/Swish on some tasks. Hidden
SELU (Scaled ELU) A self-normalizing version of ELU that keeps activations around mean=0, var=1. Use in deep fully-connected networks without normalization layers; helps stabilize training automatically. Hidden
SoftSign Smoothly scales inputs as x / (1 + |x|). Use as a lightweight, stable alternative to tanh when you want smooth gradients without exponential cost — good for RNNs or bounded outputs. Hidden
Swish Smooth, self-gated function (f(x) = x · sigmoid(x)). Use in modern deep networks (CNNs, Transformers, MLPs) where you want ReLU-like performance but with better gradient flow and smoother transitions. Hidden
SoftPlus Smooth version of ReLU (f(x) = ln(1 + eˣ)); never zeroes out completely. Use when you want ReLU-like behavior but need continuous derivatives — e.g., probabilistic networks, VAEs, or any model requiring gradient stability. Hidden, sometimes Output (positive-only regression)

Loss is chosen from the output layer: SoftMax and SimpleSoftMax outputs are trained with cross-entropy loss; every other output activation is trained with squared-error loss. SoftMax is only allowed on the output layer.

Test harness

The repository includes a complete handwritten character recognition example (digits plus upper and lower case letters):

  • TestHarness.Train trains a model from a folder of labeled images, with augmentation (rotation, shift and blur), a learning-rate scheduler, early stopping and checkpointing.
  • TestHarness.Validate measures a trained model's accuracy against a separate validation set.
  • TestHarness.Draw lets you draw characters with the mouse and see the model's predictions live (pictured above).
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 36 9/24/2026
1.2.1 373 11/13/2025
1.2.0 255 10/15/2025
1.1.6 281 5/2/2025
1.1.5 277 12/31/2024
1.1.4 248 12/3/2024
1.1.3 324 1/22/2024
1.1.2 334 11/15/2023
1.1.1 266 10/17/2023
1.1.0 261 10/12/2023
1.0.2 258 10/10/2023

Correctness overhaul: exact (gradient-checked) backpropagation, layer normalization with correct backward pass, SoftMax temperature in the gradient, continuous PiecewiseLinear, overflow-safe SoftPlus/Mish, activation-aware weight initialization, global-norm gradient clipping, AdamW with persisted optimizer state, culture-invariant parameter storage, thread-safe inference. New model file layout; files from 1.x still load.