PHP Classes

File: class.BackPropagationScale.php

Recommend this page to a friend!
  Classes of freedelta   Back Propagation Scale   class.BackPropagationScale.php   Download  
File: class.BackPropagationScale.php
Role: Class source
Content type: text/plain
Description: BackPropagation With Scale
Class: Back Propagation Scale
Implement neural networks using back propagation
Author: By
Last change: Corrected scaling functions under max-min formula and random function to make it work under Linux also
Date: 14 years ago
Size: 12,925 bytes
 

Contents

Class file image Download
<?php /** * file: class.BackPropagationScale.php * * Using artificial intelligence and NN (neuronal networks) * to solve the multiplication table problem. * * It uses a technique called back propagation, that is * the network learns by calculating the errors going * backwards: from the output, through the first hidden layers. * * The learning unit is called the perceptron: a neuron capable * of learning, connected to layers and adjusting the weights. * * Data needs to be scaled/unscaled to adjust the values common to * the neural network * * Free for educational purposes * Copyright © 2010 * * @author freedelta ( http://freedelta.free.fr ) */ error_reporting(E_ERROR); define("_RAND_MAX",32767); define("HI",0.9); define("LO",0.1); class BackPropagationScale { /* Output of each neuron */ public $output=null; /* Last calcualted output value */ public $vectorOutput=null; /* delta error value for each neuron */ public $delta=null; /* Array of weights for each neuron */ public $weight=null; /* Num of layers in the net, including input layer */ public $numLayers=null; /* Array num elments containing size for each layer */ public $layersSize=null; /* Learning rate */ public $beta=null; /* Momentum */ public $alpha=null; /* Storage for weight-change made in previous epoch (three-dimensional array) */ public $prevDwt=null; /* Data */ public $data=null; /* Test Data */ public $testData=null; /* N lines of Data */ public $NumPattern=null; /* N columns in Data */ public $NumInput=null; /* Minimum value in data set */ public $minX=0; /* Maximum value in data set */ public $maxX=1; /* Stores ann scale calculated parameters */ public $normalizeMax=null; public $normalizeMin=null; /* Holds all output data in one array */ public $output_vector=null; public function __construct($numLayers,$layersSize,$beta,$alpha,$minX,$maxX) { $this->alpha=$alpha; $this->beta=$beta; $this->minX=$minX; $this->maxX=$maxX; // Set no of layers and their sizes $this->numLayers=$numLayers; $this->layersSize=$layersSize; // seed and assign random weights for($i=1;$i<$this->numLayers;$i++) { for($j=0;$j<$this->layersSize[$i];$j++) { for($k=0;$k<$this->layersSize[$i-1]+1;$k++) { $this->weight[$i][$j][$k]=$this->rando(); } // bias in the last neuron $this->weight[$i][$j][$this->layersSize[$i-1]]=-1; } } // initialize previous weights to 0 for first iteration for($i=1;$i<$this->numLayers;$i++) { for($j=0;$j<$this->layersSize[$i];$j++) { for($k=0;$k<$this->layersSize[$i-1]+1;$k++) { $this->prevDwt[$i][$j][$k]=(double)0.0; } } } } public function rando() { $randValue = LO + (HI - LO) * mt_rand(0, _RAND_MAX)/_RAND_MAX; return $randValue;//32767 } /* --- sigmoid function */ public function sigmoid($inputSource) { return (double)(1.0 / (1.0 + exp(-$inputSource))); } /* --- mean square error */ public function mse($target) { $mse=0; for($i=0;$i<$this->layersSize[$this->numLayers-1];$i++) { $mse+=($target-$this->output[$this->numLayers-1][$i])*($target-$this->output[$this->numLayers-1][$i]); } return $mse/2; } /* --- returns i'th outputput of the net */ public function Out($i) { return $this->output[$this->numLayers-1][$i]; } /* --- * Feed forward one set of input * to update the output values for each neuron. This function takes the input * to the net and finds the output of each neuron */ public function ffwd($inputSource) { $sum=0.0; $numElem=count($inputSource); // assign content to input layer for($i=0;$i<$numElem;$i++) { $this->output[0][$i]=$inputSource[$i]; // outputput_from_neuron(i,j) Jth neuron in Ith Layer } // assign output (activation) value to each neuron usng sigmoid func for($i=1;$i<$this->numLayers;$i++) // For each layer { for($j=0;$j<$this->layersSize[$i];$j++) // For each neuron in current layer { $sum=0.0; for($k=0;$k<$this->layersSize[$i-1];$k++) // For each input from each neuron in preceeding layer { $sum+=$this->output[$i-1][$k]*$this->weight[$i][$j][$k]; // Apply weight to inputs and add to sum } // Apply bias $sum+=$this->weight[$i][$j][$this->layersSize[$i-1]]; // Apply sigmoid function $this->output[$i][$j]=$this->sigmoid($sum); } } } /* --- Backpropagate errors from outputput layer back till the first hidden layer */ public function bpgt($inputSource,$target) { /* --- Update the output values for each neuron */ $this->ffwd($inputSource); /////////////////////////////////////////////// /// FIND DELTA FOR OUPUT LAYER (Last Layer) /// /////////////////////////////////////////////// for($i=0;$i<$this->layersSize[$this->numLayers-1];$i++) { $this->delta[$this->numLayers-1][$i]=$this->output[$this->numLayers-1][$i]*(1-$this->output[$this->numLayers-1][$i])*($target-$this->output[$this->numLayers-1][$i]); } ///////////////////////////////////////////////////////////////////////////////////////////// /// FIND DELTA FOR HIDDEN LAYERS (From Last Hidden Layer BACKWARDS To First Hidden Layer) /// ///////////////////////////////////////////////////////////////////////////////////////////// for($i=$this->numLayers-2;$i>0;$i--) { for($j=0;$j<$this->layersSize[$i];$j++) { $sum=0.0; for($k=0;$k<$this->layersSize[$i+1];$k++) { $sum+=$this->delta[$i+1][$k]*$this->weight[$i+1][$k][$j]; } $this->delta[$i][$j]=$this->output[$i][$j]*(1-$this->output[$i][$j])*$sum; } } //////////////////////// /// MOMENTUM (Alpha) /// //////////////////////// for($i=1;$i<$this->numLayers;$i++) { for($j=0;$j<$this->layersSize[$i];$j++) { for($k=0;$k<$this->layersSize[$i-1];$k++) { $this->weight[$i][$j][$k]+=$this->alpha*$this->prevDwt[$i][$j][$k]; } $this->weight[$i][$j][$this->layersSize[$i-1]]+=$this->alpha*$this->prevDwt[$i][$j][$this->layersSize[$i-1]]; } } /////////////////////////////////////////////// /// ADJUST WEIGHTS (Using Steepest Descent) /// /////////////////////////////////////////////// for($i=1;$i<$this->numLayers;$i++) { for($j=0;$j<$this->layersSize[$i];$j++) { for($k=0;$k<$this->layersSize[$i-1];$k++) { $this->prevDwt[$i][$j][$k]=$this->beta*$this->delta[$i][$j]*$this->output[$i-1][$k]; $this->weight[$i][$j][$k]+=$this->prevDwt[$i][$j][$k]; } /* --- Apply the corrections */ $this->prevDwt[$i][$j][$this->layersSize[$i-1]]=$this->beta*$this->delta[$i][$j]; $this->weight[$i][$j][$this->layersSize[$i-1]]+=$this->prevDwt[$i][$j][$this->layersSize[$i-1]]; } } } /////////////////////////////// /// SCALING FUNCTIONS BLOCK /// /////////////////////////////// /* --- Set scaling parameters */ public function setScaleOutput($data) { $oldMin=$data[0][0]; $oldMax=$oldMin; $numElem=count($data[0]); /* --- First calcualte minimum and maximum */ for($i=0;$i<$this->NumPattern;$i++) { $oldMin=$data[$i][0]; $oldMax=$oldMin; for($j=1;$j<$numElem;$j++) { // Min if($oldMin > $data[$i][$j]) { $oldMin=$data[$i][$j]; } // Max if($oldMax < $data[$i][$j]) { $oldMax=$data[$i][$j]; } } $this->normalizeMin[$i]=$oldMin; $this->normalizeMax[$i]=$oldMax; } } /* --- Scale input data to range before feeding it to the network */ /* x - Min t = (HI -LO) * (---------) + LO Max-Min */ public function scale($data) { $this->setScaleOutput($data); $numElem=count($data[0]); $temp=0.0; for( $i=0; $i < $this->NumPattern; $i++ ) { for($j=0;$j<$numElem;$j++) { $temp=(HI-LO)*(($data[$i][$j] - $this->normalizeMin[$i]) / ($this->normalizeMax[$i] - $this->normalizeMin[$i])) + LO; $data[$i][$j]=$temp; } } return $data; } /* --- Unscale output data to original range */ /* x - LO t = (Max-Min) * (---------) + Min HI-LO */ public function unscaleOutput($output_vector) { $temp=0.0; for( $i=0; $i < $this->NumPattern; $i++ ) { $temp=($this->normalizeMax[$i]-$this->normalizeMin[$i]) * (($output_vector[$i] - LO) / (HI-LO)) + $this->normalizeMin[$i] ; $unscaledVector[$i] =$temp; } return $unscaledVector; } public function Run($dataX,$testDataX) { /* --- Threshhold - thresh (value of target mse, training stops once it is achieved) */ $Thresh = 0.00001; $numEpoch = 200000; $MSE=0.0; $this->NumPattern=count($dataX); $this->NumInput=count($dataX[0]); /* --- Pre-process data: Scale input and test values */ $data=$this->scale($dataX); /* --- Test data=(data-1 column) */ for($i=0;$i<$this->NumPattern;$i++) { for($j=0;$j<$this->NumInput-1;$j++) { $testData[$i][$j]=$data[$i][$j]; } } /* --- Start training: looping through epochs and exit when MSE error < Threshold */ echo "\nNow training the network...."; for($e=0;$e<$numEpoch;$e++) { /* -- Backpropagate */ $this->bpgt($data[$e%$this->NumPattern],$data[$e%$this->NumPattern][$this->NumInput-1]); $MSE=$this->mse($data[$e%$this->NumPattern][$this->NumInput-1]); if($e==0) { echo "\nFirst epoch Mean Square Error: $MSE"; } if( $MSE < $Thresh) { echo "\nNetwork Trained. Threshold value achieved in ".$e." iterations."; echo "\nMSE: ".$MSE; break; } } echo "\nLast epoch Mean Square Error: $MSE"; echo "\nNow using the trained network to make predictions on test data....\n"; for ($i = 0 ; $i < $this->NumPattern; $i++ ) { $this->ffwd($testData[$i]); $this->vectorOutput[]=(double)$this->Out(0); } $out=$this->unscaleOutput($this->vectorOutput); for($col=1;$col<$this->NumInput;$col++) { echo "Input$col\t"; } echo "Predicted \n"; for ($i = 0 ; $i < $this->NumPattern; $i++ ) { for($j=0;$j<$this->NumInput-1;$j++) { echo " ".$testDataX[$i][$j]." \t\t"; } echo " " .abs($out[$i])."\n"; } } } /* --- Sample use */ // Mutliplication data: 1 x 1 = 1, 1 x 2 = 2,.. etc $data=array(0=>array(1,1,1), 1=>array(1,2,2), 2=>array(1,3,3), 3=>array(1,4,4), 4=>array(1,5,5), 5=>array(2,1,2), 6=>array(2,2,4), 7=>array(2,3,6), 8=>array(2,4,8), 9=>array(2,5,10), 10=>array(3,1,3), 11=>array(3,2,6), 12=>array(3,3,9), 13=>array(3,4,12), 14=>array(3,5,15), 15=>array(4,1,4), 16=>array(4,2,8), 17=>array(4,3,12), 18=>array(4,4,16), 19=>array(4,5,20), 20=>array(5,1,5), 21=>array(5,2,10), 22=>array(5,3,15), 23=>array(5,4,20), 24=>array(5,5,25) ); // 1 x 1 =? $testData=array(0=>array(1,1), 1=>array(1,2), 2=>array(1,3), 3=>array(1,4), 4=>array(1,5), 5=>array(2,1), 6=>array(2,2), 7=>array(2,3), 8=>array(2,4), 9=>array(2,5), 10=>array(3,1), 11=>array(3,2), 12=>array(3,3), 13=>array(3,4), 14=>array(3,5), 15=>array(4,1), 16=>array(4,2), 17=>array(4,3), 18=>array(4,4), 19=>array(4,5), 20=>array(5,1), 21=>array(5,2), 22=>array(5,3), 23=>array(5,4), 24=>array(5,5) ); $layersSize=array(3,2,1); $numLayers = count($layersSize); // Learing rate - beta // momentum - alpha $beta = 0.3; $alpha = 0.1; $minX=1; $maxX=25; // Creating the net $bp=new BackPropagationScale($numLayers,$layersSize,$beta,$alpha,$minX,$maxX); $bp->Run($data,$testData); ?>