[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/t3db0t/Neuroduino/master/Neuroduino.cpp [Back]  [Original]

/*
 *  Neuroduino.c
 *  
 *  Arduino Neural Network Library
 *  Adapted & simplified from:
 *  http://www.neural-networks-at-your-fingertips.com/bpn.html
 *
 *  Implements a simple feedforward perceptron network
 * 
 *  Created by Ted Hayes on 4/15/10.
 *  Copyright 2010 Limina.Studio. All rights reserved.
 *
 */

#include "WProgram.h"
#include "Neuroduino.h"

Neuroduino::Neuroduino(){};

Neuroduino::Neuroduino(int nodeArray[], int numLayers, double eta = 0.1, double theta = 0.0, boolean debug = false) {
	// Constructor
	_debug = debug;
	trace("Neuroduino::Neuroduino\n");
	
	_numLayers = numLayers;
	_output = (int*) calloc(nodeArray[_numLayers-1], sizeof(int));
	
	// allocate structs & initialize network
	
	int i, j;
	
	_net.Layer = (LAYER**) calloc(_numLayers, sizeof(LAYER*));
	
	for (i=0; i < _numLayers; i++) {
		// 2D array of the network's layers
		//_output[i] = 0;
		_net.Layer[i] = (LAYER*) malloc(sizeof(LAYER));
		_net.Layer[i]->Units = nodeArray[i];		
		_net.Layer[i]->Output = (int*) calloc(nodeArray[i], sizeof(int));
		
		// 2D array of weights for each pair of nodes between layers
		_net.Layer[i]->Weight = (VAL**) calloc(nodeArray[i]+1, sizeof(VAL*));
		
		if (i!=0) {
			for (j=0; jWeight[j] = (VAL*) calloc(nodeArray[i-1], sizeof(VAL));
			}
		}
	}
	
	_net.InputLayer = _net.Layer[0];
	_net.OutputLayer = _net.Layer[_numLayers-1];
	_net.Eta = eta;		// learning rate
	_net.Theta = theta;	// threshold
}

/********* UTILITIES *********/

//just for testing alternative ways of storing the values... (for now is the same: DOUBLE)
VAL Neuroduino::doubleToVal(double dValue) {
	return (VAL) dValue;
}

double Neuroduino::randomEqualDouble(double Low, double High) {
	return ((double) rand() / RAND_MAX) * (High-Low) + Low;
}

void Neuroduino::printNet(){
	if (_debug) {
		int l,i,j;
		
		//Serial.print("weights of layer 0 test: ");
		//Serial.println(_net.Layer[0]->Weight[0][0], DEC);
		
		for (l=1; lWeight[i][j], 3);
					trace("\t");
				}
				trace("\n");
			}
			trace("\n");
		}
		trace("\n");
	}
}

// free memory check
// from: http://forum.pololu.com/viewtopic.php?f=10&t=989#p4218
int Neuroduino::get_free_memory(){
	int free_memory;
	if((int)__brkval == 0)
		free_memory = ((int)&free_memory) - ((int)&__bss_end);
	else
		free_memory = ((int)&free_memory) - ((int)__brkval);
	
	return free_memory;
}

/********* PRIVATE *********/

void Neuroduino::randomizeWeights() {
	int l,i,j;
	double temp;
	
	for (l=1; lWeight[i][j] = doubleToVal(randomEqualDouble(-0.5, 0.5));
			}
		}
	}
}

void Neuroduino::setInput(int inputs[]){
	int i;
	for (i=0; iUnits; i++) {
		_net.InputLayer->Output[i] = inputs[i];
	}
}

int* Neuroduino::getOutput(){
	
	return _output;
	
}

int Neuroduino::signThreshold(double sum){	
	if (sum >= _net.Theta) {
		return 1;
	} else {
		return -1;
	}
}

double Neuroduino::weightedSum(int l, int node){
	// calculates input activation for a particular neuron
	int i;
	double currentWeight, sum = 0.0;
	
	for (i=0; iUnits; i++) {
		currentWeight = _net.Layer[l]->Weight[node][i];		
		sum += currentWeight * _net.Layer[l-1]->Output[i];
	}
	
	return sum;
}

void Neuroduino::adjustWeights(int trainArray[]){
	int l,i,j;
	int in,out, error;
	int activation;	// for each "rightmost" node
	double delta;
	
	for (l=1; lOutput[j];
				
				delta = _net.Eta * in * error;
				_net.Layer[l]->Weight[i][j] += delta;
			}
		}
	}
}

void Neuroduino::simulateNetwork(){
	/*****
	 Calculate activations of each output node
	 *****/
	int l,j;
	
	for (l=_numLayers-1; l>0; l--) {
		// step backwards through layers
		// TODO: this will only work for _numLayers = 2!
		for (j=0; j < _net.Layer[l]->Units; j++) {
			_output[j] = signThreshold(weightedSum(1, j));
		}
	}
}

/********* PUBLIC *********/

void Neuroduino::train(int inputArray[], int trainArray[]) {
	trace("Neuroduino::train\n");
	
	setInput(inputArray);
	adjustWeights(trainArray);
	
}

int* Neuroduino::simulate(int inputArray[]) {
	// introduce an input stimulus, simulate the network,
	// and return an output array
	trace("Neuroduino::simulate\n");
	setInput(inputArray);
	simulateNetwork();
		
	return _output;
}

void Neuroduino::trace(char *message) {
	if(_debug){
		Serial.print(message);
	}
}

Web Proxy Viewer  |  New URL  |  Original Page