Artificial Neural Network in PHP

Introduction

Operation Flashpoint is an immersive combat simulation game thanks to the challenging realism and an assortment of weapons with realistic ballistics and sound effects. But my favourite feature is the artificial intelligence that drives the non-player characters. Seeing how these computer opponents are able to learn and adapt to changing situations has rekindled my interest in AI.

In this article I describe how I implemented an artificial neural network (ANN) in PHP. Theories, formulae, and mathematical proofs are omitted for brevity.

I also make the source code available.

What is an artificial neural network?

An artificial neural network is a model mimicking how the brain learns and how neurons interact with each other during this process. It is based on the study of reinforcement learning in the brain. For a more detailed definition, see here.

There are several types of ANN, but this implementation will model the feed-forward, multi-layer neural network.

Learning

An ANN learns by reinforcing or weakening the connections between its neurons, in the same way that the natural brain works according to science. Of the multiple learning (or training) algorithms available, this implementation uses backpropagation (or BACKPROP).

Why PHP?

Several tutorials for developing ANNs already exist on the Internet. However, most of those provide example code written in C, C++, or Java, which does not make them suitable for people who understand only PHP.

I picked PHP for this implementation in order to take advantage of the following.

  • Built-in vector functions
  • Shorter coding-debugging cycle
  • Ability to code in object-oriented style

Basics

If you skipped the theory of ANN, here are the basics things you must know.

A multi-layer ANN consists of at least three layers: one input layer, one hidden layer and one output layer. There can be multiple hidden layers, each with multiple neurons (hidden neurons).

In a feed-forward ANN each input is fed into each neuron of the first hidden layer whose outputs are fed into the neurons of the next layer, and so on, until the output neurons receive the final inputs and produce the final outputs.

Additionally, a bias input may be fed into each layer for better results. See  this explanation of the importance of the bias input.

Each input has a weight that is initially set to a random value — usually between -1.0 and 1.0. During training the weights are adjusted using an error-correction algorithm. This is repeated over as many iterations as required to make the ANN produce the desired outputs from a given set of inputs. In essence the final weights represent the “knowledge” of the ANN.

The simplest definition of the output of an artificial neuron is the result obtained when the sum of its weighted inputs is passed through a stepping function. In this implementation, the following sigmoid function is used.

f(x) = 1 / (1 + exp(-x) )

where exp() is an exponential function.

Given three inputs x1, x2 and x3, with weights w1, w2, w3, respectively, a neuron outputs a value obtained as follows:

Step 1 – Calculating the sum of weighted inputs

sum = (x1 w1) + (x2 w2) + (x3 * w3)

Step 2 – Calculating the output

output = 1 / (1 + exp(-1 * sum) )

Given an ANN with n output neurons, n outputs are expected. Each output is calculated using the formulae above to give the final output — a vector of outputs, that is.

Note that the above sigmoid function only outputs results between 0 and 1; therefore, a scaling function must be applied to the results to bring the outputs within the desired range

An ANN using the BACKPROP algorithm is trained by recursively feeding a set of inputs into it and adjusting its weights according to the discrepancy between the actual outputs and desired outputs. The recursion lasts until an acceptable discrepancy is reached.

The adjustment (or weight change) for each input is proportional to its value. So,

weight change = learning rate input  delta

The learning rate is an arbitrary value that dictates how fast the network should learn. The delta is the rate of change of the discrepancy with respect to the output for the neuron; it is determined by using the delta rule. For a general definition, see:

http://uhaweb.hartford.edu/compsci/neural-networks-delta-rule.html

http://diwww.epfl.ch/mantra/tutorial/english/apb/html/theory.html

Calculation of the delta for an output neuron is easily obtained by using the following formula.

delta = actual output (1 – actual output) (desired output – actual output)

Calculation of the delta for a hidden neuron is more complex because it depends on the delta values of the neurons of the previous layer as the adjustment proceeds from the output layer to the input layer.

To calculate the delta for a neuron which feeds its output to n neurons in the next layer, the following steps are required.

Step 1 – Calculate the product of the weight [for the output] and the delta of each of the n neurons

sum += weight * deltan

for each delta of the n neurons, where deltan is the delta for the n-th neuron.

Step 2 – Calculate the delta for the hidden neuron

delta = actual output (1 – actual output) sum

The concepts and formulae above are sufficient for a successful implementation.

Components

The entire implementation consists of four classes.

Maths

This class provides two static methods, random() and sigmoid() respectively.

random() generates random numbers within the limits specified
sigmoid() implements the sigmoid function described earlier

Neuron

This class abstracts a neuron. It holds an array of inputs and weights; the output; and the calculated delta.

The output is calculated by calling the activate() method and read by calling the getOutput() accessor method. The method setDelta() sets the delta for the neuron, and adjustWeights() adjust the weights according to the delta and the learning rate.

Layer

This class abstracts a network layer. It contains a vector of neurons and outputs. It also provides functions to calculate the deltas of each neuron according to the type of the layer. In the case of an output layer, the function calculateOutputDeltas() is used; in the case of a hidden layer, the function calculateHiddenDeltas() is used. These two functions set the delta of each neuron of the layer. The method activate() activates each neuron in turn. The accessor method getOutputs() returns the outputs of all the neurons as a vector; these are then either fed into the next layer’s neurons, or returned as the network output.

Network

This class abstracts the artificial neural network. The constructor takes arguments for the number of hidden layers, the number of neurons per hidden layer and the number of outputs.

The most important methods of this class are setInputs(), train(), activate() and getOutputs(). The network takes a vector of values as input and outputs a vector of values as output.

The methods save() and load() save the network architecture and weights and load a stored network, respectively.

Installation and usage

Contents of archive

The archive contains the following files.

nn.php – the ANN implementation classes
XOR_Training.php – the sample script for training a XOR
XOR_Run.php – the sample script to evaluate XOR operations
xor.dat – the saved XOR network architecture and weights

Creating a neural network

To create an ANN, you will need to include the file nn.php. Using the classes, you can structure your ANN as you wish. Once you have trained your network, you can save it to a file.

To use your network for evaluations, you need to restore the network from the saved file, feed it with inputs and get the output.

Training

Training is achieved by feeding a well prepared set of inputs and desired outputs to the network.

For example,


        ...

        // training inputs
        $inputs = array(
            array(0, 0),
            array(0, 1),
            array(1, 0),
            array(1, 1)
        );

        // desired outputs
        $outputs = array(
            array(0),
            array(1),
            array(1),
            array(0)
        );

        // recurse the training until desired results are obtained
        for ($i = 0; $i setInputs($inputs[$j]);
            $network->train(0.5, $outputs[$j]); 
        }

        // save the network to a file
        $network->save(xor.dat);

It is recommended that the network be saved at regular intervals to avoid re-starting the network each time.

Evaluating

To evaluate a set of inputs, the network needs to be loaded from the file and fed with the inputs; and the activate() method called. The output is obtained by calling the getOutputs() method.

For example,


        $network = Network::load(xor.dat);

        if ($network == null) {
            echo nNetwork not found. Creating a new one...;
            $network =& new Network(1, 10, 1);
        }

        $inputs = array(
            array(0, 0),
            array(0, 1),
            array(1, 0),
            array(1, 1)
        );

        for ($i = 0; $i setInputs($inputs[$i]);
            $network->activate();

            echo n;
            print_r($network->getOutputs() );
        }

UPDATE:

Fixed bug caused by weights not being initialised in the hidden layers.

Join the Conversation

10 Comments

  1. If you use PHP as an Apache-module, the following problem can appear:
    When you load, train and save a network and in the same PHP-script you want the network to be loaded again, the network is not loaded correctly, because the function filesize() returns the old size of the serialised network (if the new filesize is larger than the old filesize, the network is broken and not loaded).

    To fix this, add a clearstatcache() in the network-load-function (in nn.php):

    function &load($filename) {
      if (file_exists($filename) ) {
        clearstatcache();
        $f = fopen($filename, "r");
        $serialised = fread($f, filesize($filename));
    [...]
    
  2. sir,
    can u please send me the C code for XOr problem using ANN with back propagation.

  3. The whole point of this article is to show how to write an ANN in PHP. There are many other examples in C that you can get elsewhere on the Internet. Unfortunately, I do not have any.

  4. Where I can download the files?

    nn.php – the ANN implementation classes
    XOR_Training.php – the sample script for training a XOR
    XOR_Run.php – the sample script to evaluate XOR operations
    xor.dat – the saved XOR network architecture and weights

  5. Not proper SOM, but by combining two networks and training one as a trainer, you can achieve something close enough.

Leave a comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.