Perceptron in pure PHP

This entry page combines two separate runnable examples: a classic perceptron and a minimal MLP in PHP. Choose the implementation you need below and run it independently.

Classic Rosenblatt perceptron (standalone run)

A minimal implementation of the classic perceptron: weighted sum, threshold activation, and training with the Rosenblatt update rule.

 
<?php

class Perceptron {
    
// One weight per input feature.
    
private array $weights;

    private 
float $bias;

    private 
float $learningRate;

    public function 
__construct(int $nFeaturesfloat $lr 0.1) {
        
$this->learningRate $lr;
        
$this->weights array_fill(0$nFeatures0.0);
        
$this->bias 0.0;
    }

    public function 
getWeights(): array {
        return 
$this->weights;
    }

    public function 
getBias(): float {
        return 
$this->bias;
    }

    private function 
activation(float $z): int {
        
// Binary step activation.
        
return $z 0;
    }

    public function 
predict(array $x): int {
        
$z $this->bias;

        foreach (
$x as $i => $value) {
            
$z += $this->weights[$i] * $value;
        }

        return 
$this->activation($z);
    }

    public function 
train(array $X, array $yint $epochs 100): void {
        
// Rosenblatt update rule over multiple passes through the dataset.
        
for ($e 0$e $epochs$e++) {
            foreach (
$X as $i => $sample) {
                
$prediction $this->predict($sample);
                
$error $y[$i] - $prediction;

                foreach (
$sample as $j => $value) {
                    
$this->weights[$j] += $this->learningRate $error $value;
                }

                
$this->bias += $this->learningRate $error;
            }
        }
    }
}

One hidden layer and forward pass (standalone run)

A simplified one-hidden-layer MLP without bias terms: this example demonstrates only the forward pass on an input vector.

 
<?php

class SimpleMLP {
    
// Hidden-layer weights: [hidden_neuron][input_feature].
    
private array $W1;
    private array 
$W2;
    private 
float $lr;
    private array 
$hidden;

    public function 
__construct(int $inputSizeint $hiddenSizefloat $lr 0.01) {
        
$this->lr $lr;

        
// Random initialization in [0, 1] for tutorial simplicity.
        
$this->W1 = [];

        for (
$i 0$i $hiddenSize$i++) {
            
$this->W1[$i] = array_fill(0$inputSizemt_rand() / mt_getrandmax());
        }

        
$this->W2 array_fill(0$hiddenSizemt_rand() / mt_getrandmax());
    }

    public function 
getW1() {
        return 
$this->W1;
    }

    public function 
getW2() {
        return 
$this->W2;
    }

    public function 
getHidden() {
        return 
$this->hidden;
    }

    private function 
relu(float $z): float {
        return 
max(0$z);
    }

    public function 
forward(array $x): float {
        
// Compute hidden activations.
        
$hidden = [];

        foreach (
$this->W1 as $weights) {
            
$z 0.0;

            foreach (
$weights as $i => $w) {
                
$z += $w $x[$i];
            }

            
$hidden[] = $this->relu($z);
        }

        
$this->hidden $hidden;

        
$output 0.0;

        
// Linear output from hidden activations.
        
foreach ($hidden as $i => $h) {
            
$output += $this->W2[$i] * $h;
        }

        return 
$output;
    }
}