Classification
Learn to build classification models with AiDotNet.
What is Classification?
Classification is a supervised learning task where the goal is to predict discrete class labels from input features. Examples include:
- Email spam detection (spam/not spam)
- Image recognition (cat/dog/bird)
- Disease diagnosis (positive/negative)
Types of Classification
Binary Classification
Exactly two classes. Example: Is this email spam?
Multi-class Classification
Three or more classes. Example: What species is this flower?
Quick Start
using AiDotNet;
using AiDotNet.Classification.Ensemble;
using AiDotNet.Data.Loaders;
using AiDotNet.Models.Options;
using AiDotNet.Tensors.LinearAlgebra;
// Iris dataset samples: 4 features, 3 species (0=setosa, 1=versicolor, 2=virginica)
double[][] features =
{
new[] { 5.1, 3.5, 1.4, 0.2 }, new[] { 4.9, 3.0, 1.4, 0.2 },
new[] { 7.0, 3.2, 4.7, 1.4 }, new[] { 6.4, 3.2, 4.5, 1.5 },
new[] { 6.3, 3.3, 6.0, 2.5 }, new[] { 5.8, 2.7, 5.1, 1.9 }
};
double[] labels = { 0, 0, 1, 1, 2, 2 };
var X = ToMatrix(features);
var y = new Vector<double>(labels);
var result = await new AiModelBuilder<double, Matrix<double>, Vector<double>>()
.ConfigureModel(new RandomForestClassifier<double>(
new RandomForestClassifierOptions<double> { NEstimators = 100 }))
.ConfigureDataLoader(DataLoaders.FromMatrixVector(X, y))
.BuildAsync();
var newFlower = new Matrix<double>(1, 4);
foreach (var (v, j) in new[] { 5.9, 3.0, 5.1, 1.8 }.Select((v, j) => (v, j)))
newFlower[0, j] = v;
Console.WriteLine($"Predicted class: {(int)result.Predict(newFlower)[0]}");
// NOTE: these are computed on the SAME data the model was fit on, so they are resubstitution
// (training-set) metrics — optimistic, not a validation estimate. Use a holdout split to judge
// generalization.
var stats = result.GetDataSetStats(X, y);
Console.WriteLine($"Training accuracy: {stats.ErrorStats.Accuracy:P2}, F1: {stats.ErrorStats.F1Score:P2}");
static Matrix<double> ToMatrix(double[][] rows)
{
var m = new Matrix<double>(rows.Length, rows[0].Length);
for (int i = 0; i < rows.Length; i++)
for (int j = 0; j < rows[0].Length; j++)
m[i, j] = rows[i][j];
return m;
}
Available Classifiers
Swap the ConfigureModel(...) argument to change algorithm.
| Family | Classifiers |
|---|---|
| Tree-based | RandomForestClassifier, GradientBoostingClassifier, DecisionTreeClassifier, ExtraTreesClassifier, AdaBoostClassifier |
| Linear | LogisticRegression, LinearSupportVectorClassifier |
| Bayesian | GaussianNaiveBayes, MultinomialNaiveBayes, BernoulliNaiveBayes, ComplementNaiveBayes |
| Distance-based | KNeighborsClassifier |
Naive Bayes
using AiDotNet;
using AiDotNet.Classification.NaiveBayes;
using AiDotNet.Data.Loaders;
using AiDotNet.Tensors.LinearAlgebra;
double[][] features =
{
new[] { 5.1, 3.5, 1.4, 0.2 }, new[] { 4.9, 3.0, 1.4, 0.2 },
new[] { 7.0, 3.2, 4.7, 1.4 }, new[] { 6.4, 3.2, 4.5, 1.5 },
new[] { 6.3, 3.3, 6.0, 2.5 }, new[] { 5.8, 2.7, 5.1, 1.9 }
};
double[] labels = { 0, 0, 1, 1, 2, 2 };
var result = await new AiModelBuilder<double, Matrix<double>, Vector<double>>()
.ConfigureModel(new GaussianNaiveBayes<double>())
.ConfigureDataLoader(DataLoaders.FromArrays(features, labels))
.BuildAsync();
Console.WriteLine("Trained a Gaussian Naive Bayes classifier.");
Neural Network
using AiDotNet;
using AiDotNet.Data.Loaders;
using AiDotNet.Enums;
using AiDotNet.NeuralNetworks;
using AiDotNet.Tensors.LinearAlgebra;
var rng = new Random(42);
var trainX = new Tensor<double>(new[] { 120, 16 });
var trainY = new Tensor<double>(new[] { 120, 3 });
for (int i = 0; i < 120; i++)
{
for (int j = 0; j < 16; j++) trainX[new[] { i, j }] = rng.NextDouble();
trainY[new[] { i, i % 3 }] = 1.0;
}
var result = await new AiModelBuilder<double, Tensor<double>, Tensor<double>>()
.ConfigureModel(new NeuralNetwork<double>(new NeuralNetworkArchitecture<double>(
inputFeatures: 16, numClasses: 3, complexity: NetworkComplexity.Medium)))
.ConfigureGpuAcceleration()
.ConfigureDataLoader(DataLoaders.FromTensors(trainX, trainY))
.BuildAsync();
Console.WriteLine($"Output shape: [{string.Join(", ", result.Predict(trainX).Shape)}]");
Cross-Validation
Validate with k-fold cross-validation (a StratifiedKFoldCrossValidator is also available for preserving class balance):
using AiDotNet;
using AiDotNet.Classification.Ensemble;
using AiDotNet.CrossValidators;
using AiDotNet.Data.Loaders;
using AiDotNet.Models.Options;
using AiDotNet.Tensors.LinearAlgebra;
double[][] features =
{
new[] { 5.1, 3.5, 1.4, 0.2 }, new[] { 4.9, 3.0, 1.4, 0.2 }, new[] { 5.0, 3.4, 1.5, 0.2 },
new[] { 7.0, 3.2, 4.7, 1.4 }, new[] { 6.4, 3.2, 4.5, 1.5 }, new[] { 6.9, 3.1, 4.9, 1.5 },
new[] { 6.3, 3.3, 6.0, 2.5 }, new[] { 5.8, 2.7, 5.1, 1.9 }, new[] { 7.1, 3.0, 5.9, 2.1 }
};
double[] labels = { 0, 0, 0, 1, 1, 1, 2, 2, 2 };
var result = await new AiModelBuilder<double, Matrix<double>, Vector<double>>()
.ConfigureModel(new RandomForestClassifier<double>(
new RandomForestClassifierOptions<double> { NEstimators = 50 }))
.ConfigureCrossValidation(new KFoldCrossValidator<double, Matrix<double>, Vector<double>>())
.ConfigureDataLoader(DataLoaders.FromArrays(features, labels))
.BuildAsync();
if (result.CrossValidationResult is not null)
Console.WriteLine($"Cross-validation folds: {result.CrossValidationResult.FoldResults.Count}");
Evaluation Metrics
result.GetDataSetStats(X, y).ErrorStats carries every classification metric — accuracy, precision, recall, F1, and AUC.
using AiDotNet;
using AiDotNet.Classification.Ensemble;
using AiDotNet.Data.Loaders;
using AiDotNet.Models.Options;
using AiDotNet.Tensors.LinearAlgebra;
double[][] data =
{
new[] { 0.1, 0.9 }, new[] { 0.2, 0.8 }, new[] { 0.15, 0.85 },
new[] { 0.9, 0.1 }, new[] { 0.8, 0.2 }, new[] { 0.85, 0.15 }
};
double[] labels = { 0, 0, 0, 1, 1, 1 };
var X = ToMatrix(data);
var y = new Vector<double>(labels);
var result = await new AiModelBuilder<double, Matrix<double>, Vector<double>>()
.ConfigureModel(new RandomForestClassifier<double>(
new RandomForestClassifierOptions<double> { NEstimators = 50 }))
.ConfigureDataLoader(DataLoaders.FromMatrixVector(X, y))
.BuildAsync();
var s = result.GetDataSetStats(X, y).ErrorStats;
Console.WriteLine($"Accuracy: {s.Accuracy:P2}");
Console.WriteLine($"Precision: {s.Precision:P2}");
Console.WriteLine($"Recall: {s.Recall:P2}");
Console.WriteLine($"F1 Score: {s.F1Score:P2}");
Console.WriteLine($"AUC-ROC: {s.AUCROC:F4}");
static Matrix<double> ToMatrix(double[][] rows)
{
var m = new Matrix<double>(rows.Length, rows[0].Length);
for (int i = 0; i < rows.Length; i++)
for (int j = 0; j < rows[0].Length; j++)
m[i, j] = rows[i][j];
return m;
}
Best Practices
- Start simple:
LogisticRegressionorGaussianNaiveBayesmake strong baselines. - Check class balance: use
StratifiedKFoldCrossValidatorfor imbalanced data. - Feature scaling: linear and distance-based models benefit from
ConfigurePreprocessing(...). - Cross-validate: prefer cross-validation over a single train/test split.
- Watch overfitting: compare
result.Evaluation.TrainingSetagainstresult.Evaluation.ValidationSet.
Next Steps
- Regression Tutorial — for predicting continuous values
- NLP Tutorial — for text classification