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.

 
<?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%