Logistic regression
MNIST. Binary classification: 0 vs 1
Implementation in pure PHP
This is one of the most famous teaching cases in machine learning. It is simple to state, yet it clearly shows how the model works – and where it starts to break down. Here we make an important turn in the book: we move from tabular data to images. Case goal: learn to classify digit images as "0" or "1" with logistic regression and understand the limitations of a linear model.
Pure PHP implementation uses a toy MNIST-like dataset with flattened 28x28 images and the standard logistic regression training loop.
Example of use
<?php
use app\classes\LogisticRegression;
use app\classes\MnistLoader;
[$trainSamples, $trainLabels] = MnistLoader::load('train.csv', normalize: true);
[$testSamples, $testLabels] = MnistLoader::load('test.csv', normalize: true);
echo 'Train samples handled: ' . number_format(count($trainSamples)) . PHP_EOL;
echo 'Test samples handled: ' . number_format(count($testSamples)) . PHP_EOL . PHP_EOL;
$model = new LogisticRegression(784, 0.1);
$model->train($trainSamples, $trainLabels, epochs: $epochs = 5);
echo 'Number of epochs: ' . $epochs . PHP_EOL . PHP_EOL;
// Calculate model accuracy
$score = $model->score($testSamples, $testLabels);
echo 'Train samples handled: ' . number_format(count($trainSamples)) . PHP_EOL;
echo 'Test samples handled: ' . number_format(count($testSamples)) . PHP_EOL . PHP_EOL;
echo 'Accuracy: ' . round($score * 100, 2) . '%';
Sample of digit 0
Probability of digit 0: 1
Predicted digit: 0
Sample of digit 1
Probability of digit 1: 1
Predicted digit: 1
Result:
Memory: 0 Mb
Time running: 0.001 sec.
Train samples handled: 12,666
Test samples handled: 2,116
Number of epochs: 5
Accuracy: 99.91%