在TEK271.com上可以找到另外两个对入门有用的资源:http: //www.tek271.com/?about = docs/neuralNet/IntoToNeuralNets.html 和南加州机器人学会:http:// www.rssc.org/content/introduction-neural-nets-part-1。
#include <math.h>
#include "HC89F0541.h"
#include <stdio.h>
#include <stdlib.h>
/******************************************************************
* Network Configuration - customized per network
******************************************************************/
#define PatternCount 10
#define InputNodes 7
#define HiddenNodes 8
#define OutputNodes 4
//const int PatternCount = Pattern_Count;
//const int InputNodes = Input_Nodes;
//const int HiddenNodes = Hidden_Nodes;
//const int OutputNodes = Output_Nodes;
const float LearningRate = 0.3;
const float Momentum = 0.9;
const float InitialWeightMax = 0.5;
const float Success = 0.1;//0.0004;
typedef ux8 byte;
const byte Input[PatternCount][InputNodes] = {
{ 1, 1, 1, 1, 1, 1, 0 }, // 0
{ 0, 1, 1, 0, 0, 0, 0 }, // 1
{ 1, 1, 0, 1, 1, 0, 1 }, // 2
{ 1, 1, 1, 1, 0, 0, 1 }, // 3
{ 0, 1, 1, 0, 0, 1, 1 }, // 4
{ 1, 0, 1, 1, 0, 1, 1 }, // 5
{ 0, 0, 1, 1, 1, 1, 1 }, // 6
{ 1, 1, 1, 0, 0, 0, 0 }, // 7
{ 1, 1, 1, 1, 1, 1, 1 }, // 8
{ 1, 1, 1, 0, 0, 1, 1 } // 9
};
const byte Target[PatternCount][OutputNodes] = {
{ 0, 0, 0, 0 },
{ 0, 0, 0, 1 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 1 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 1 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 1 },
{ 1, 0, 0, 0 },
{ 1, 0, 0, 1 }
};
typedef int (*func1)(int);
typedef int (*func2)(const char*, int) reentrant;
typedef int (*func3)(const char*, float) reentrant;
typedef struct S {
func1 begin;
func2 println;// = printf;
func2 print;// = printf;
func3 printf;// = printf;
}s_t;
s_t Serial;
void Uart_SendByte(unsigned char buf)
{
SCON &=~ 0x10; //失能UART1接收
SBUF = buf; //发送8位串口数据
while(!(SCON & 0x02));
SCON &=~ 0x02; //清除发送中断标志位
SCON |= 0x10; //UART1接收使能
}
char putchar(char c)
{
Uart_SendByte(c);
return c;
}
int sendmsg(const char* str, float d){
printf(str, d);
return 1;
}
/******************************************************************
* End Network Configuration
******************************************************************/
xdata int i, j, p, q, r;
xdata int ReportEvery1000;
xdata int RandomizedIndex[PatternCount];
xdata long TrainingCycle;
xdata float Rando;
xdata float Error;
xdata float Accum;
xdata float Hidden[HiddenNodes];
xdata float Output[OutputNodes];
xdata float HiddenWeights[InputNodes+1][HiddenNodes];
xdata float OutputWeights[HiddenNodes+1][OutputNodes];
xdata float HiddenDelta[HiddenNodes];
xdata float OutputDelta[OutputNodes];
xdata float ChangeHiddenWeights[InputNodes+1][HiddenNodes];
xdata float ChangeOutputWeights[HiddenNodes+1][OutputNodes];
int random(int r){
return rand() % r;
}
void toTerminal()
{
for( p = 0 ; p < PatternCount ; p++ ) {
Serial.println("\n");
Serial.print (" Training Pattern: %d ", p);
//Serial.println (p);
Serial.print (" Input ");
for( i = 0 ; i < InputNodes ; i++ ) {
Serial.print ("%d", Input[p][i]);
Serial.print (" ");
}
Serial.print (" Target ");
for( i = 0 ; i < OutputNodes ; i++ ) {
Serial.print ("%d", Target[p][i]);
Serial.print (" ");
}
/******************************************************************
* Compute hidden layer activations
******************************************************************/
for( i = 0 ; i < HiddenNodes ; i++ ) {
Accum = HiddenWeights[InputNodes][i] ;
for( j = 0 ; j < InputNodes ; j++ ) {
Accum += Input[p][j] * HiddenWeights[j][i] ;
}
Hidden[i] = 1.0/(1.0 + exp(-Accum)) ;
}
/******************************************************************
* Compute output layer activations and calculate errors
******************************************************************/
for( i = 0 ; i < OutputNodes ; i++ ) {
Accum = OutputWeights[HiddenNodes][i] ;
for( j = 0 ; j < HiddenNodes ; j++ ) {
Accum += Hidden[j] * OutputWeights[j][i] ;
}
Output[i] = 1.0/(1.0 + exp(-Accum)) ;
}
Serial.print (" Output ");
for( i = 0 ; i < OutputNodes ; i++ ) {
Serial.printf ("%f", Output[i]);
Serial.print (" ");
}
}
}
void predict(u8 *input)
{
/******************************************************************
* Compute hidden layer activations
******************************************************************/
for( i = 0 ; i < HiddenNodes ; i++ ) {
Accum = HiddenWeights[InputNodes][i] ;
for( j = 0 ; j < InputNodes ; j++ ) {
Accum += input[j] * HiddenWeights[j][i] ;
}
Hidden[i] = 1.0/(1.0 + exp(-Accum)) ;
}
/******************************************************************
* Compute output layer activations and calculate errors
******************************************************************/
for( i = 0 ; i < OutputNodes ; i++ ) {
Accum = OutputWeights[HiddenNodes][i] ;
for( j = 0 ; j < HiddenNodes ; j++ ) {
Accum += Hidden[j] * OutputWeights[j][i] ;
}
Output[i] = 1.0/(1.0 + exp(-Accum)) ;
Output[i] = Output[i] > 0.8 ? 1:0;
}
Serial.print ("result: ");
for( i = 0 ; i < OutputNodes ; i++ ) {
Serial.printf ("%f", Output[i]);
Serial.print (" ");
}
Serial.print ("\n");
}
void setup(){
Serial.begin = (9600);
Serial.println = sendmsg;
Serial.print = sendmsg;
Serial.printf = sendmsg;
//randomSeed(analogRead(3));
ReportEvery1000 = 1;
for( p = 0 ; p < PatternCount ; p++ ) {
RandomizedIndex[p] = p ;
}
}
void main(){
setup();
/******************************************************************
* Initialize HiddenWeights and ChangeHiddenWeights
******************************************************************/
for( i = 0 ; i < HiddenNodes ; i++ ) {
for( j = 0 ; j <= InputNodes ; j++ ) {
ChangeHiddenWeights[j][i] = 0.0 ;
Rando = (float)(random(100))/100;
HiddenWeights[j][i] = 2.0 * ( Rando - 0.5 ) * InitialWeightMax ;
}
}
/******************************************************************
* Initialize OutputWeights and ChangeOutputWeights
******************************************************************/
for( i = 0 ; i < OutputNodes ; i ++ ) {
for( j = 0 ; j <= HiddenNodes ; j++ ) {
ChangeOutputWeights[j][i] = 0.0 ;
Rando = (float)(random(100))/100;
OutputWeights[j][i] = 2.0 * ( Rando - 0.5 ) * InitialWeightMax ;
}
}
Serial.println("Initial/Untrained Outputs: ");
toTerminal();
/******************************************************************
* Begin training
******************************************************************/
for( TrainingCycle = 1 ; TrainingCycle < 2147483647 ; TrainingCycle++) {
/******************************************************************
* Randomize order of training patterns
******************************************************************/
for( p = 0 ; p < PatternCount ; p++) {
q = random(PatternCount);
r = RandomizedIndex[p] ;
RandomizedIndex[p] = RandomizedIndex[q] ;
RandomizedIndex[q] = r ;
}
Error = 0.0 ;
/******************************************************************
* Cycle through each training pattern in the randomized order
******************************************************************/
for( q = 0 ; q < PatternCount ; q++ ) {
p = RandomizedIndex[q];
/******************************************************************
* Compute hidden layer activations
******************************************************************/
for( i = 0 ; i < HiddenNodes ; i++ ) {
Accum = HiddenWeights[InputNodes][i] ;
for( j = 0 ; j < InputNodes ; j++ ) {
Accum += Input[p][j] * HiddenWeights[j][i] ;
}
Hidden[i] = 1.0/(1.0 + exp(-Accum)) ;
}
/******************************************************************
* Compute output layer activations and calculate errors
******************************************************************/
for( i = 0 ; i < OutputNodes ; i++ ) {
Accum = OutputWeights[HiddenNodes][i] ;
for( j = 0 ; j < HiddenNodes ; j++ ) {
Accum += Hidden[j] * OutputWeights[j][i] ;
}
Output[i] = 1.0/(1.0 + exp(-Accum)) ;
OutputDelta[i] = (Target[p][i] - Output[i]) * Output[i] * (1.0 - Output[i]) ;
Error += 0.5 * (Target[p][i] - Output[i]) * (Target[p][i] - Output[i]) ;
}
/******************************************************************
* Backpropagate errors to hidden layer
******************************************************************/
for( i = 0 ; i < HiddenNodes ; i++ ) {
Accum = 0.0 ;
for( j = 0 ; j < OutputNodes ; j++ ) {
Accum += OutputWeights[i][j] * OutputDelta[j] ;
}
HiddenDelta[i] = Accum * Hidden[i] * (1.0 - Hidden[i]) ;
}
/******************************************************************
* Update Inner-->Hidden Weights
******************************************************************/
for( i = 0 ; i < HiddenNodes ; i++ ) {
ChangeHiddenWeights[InputNodes][i] = LearningRate * HiddenDelta[i] + Momentum * ChangeHiddenWeights[InputNodes][i] ;
HiddenWeights[InputNodes][i] += ChangeHiddenWeights[InputNodes][i] ;
for( j = 0 ; j < InputNodes ; j++ ) {
ChangeHiddenWeights[j][i] = LearningRate * Input[p][j] * HiddenDelta[i] + Momentum * ChangeHiddenWeights[j][i];
HiddenWeights[j][i] += ChangeHiddenWeights[j][i] ;
}
}
/******************************************************************
* Update Hidden-->Output Weights
******************************************************************/
for( i = 0 ; i < OutputNodes ; i ++ ) {
ChangeOutputWeights[HiddenNodes][i] = LearningRate * OutputDelta[i] + Momentum * ChangeOutputWeights[HiddenNodes][i] ;
OutputWeights[HiddenNodes][i] += ChangeOutputWeights[HiddenNodes][i] ;
for( j = 0 ; j < HiddenNodes ; j++ ) {
ChangeOutputWeights[j][i] = LearningRate * Hidden[j] * OutputDelta[i] + Momentum * ChangeOutputWeights[j][i] ;
OutputWeights[j][i] += ChangeOutputWeights[j][i] ;
}
}
}
/******************************************************************
* Every 1000 cycles send data to terminal for display
******************************************************************/
ReportEvery1000 = ReportEvery1000 - 1;
if (ReportEvery1000 == 0)
{
Serial.println("\n");
Serial.println("\n");
Serial.print ("TrainingCycle: %d",TrainingCycle );
//Serial.print (TrainingCycle);
Serial.printf (" Error = %f", Error);
//Serial.println (Error, 5);
toTerminal();
if (TrainingCycle==1)
{
ReportEvery1000 = 999;
}
else
{
ReportEvery1000 = 1000;
}
}
/******************************************************************
* If error rate is less than pre-determined threshold then end
******************************************************************/
if( Error < Success ) break ;
}
Serial.println("\n");
Serial.println("\n");
Serial.print ("TrainingCycle: %d", TrainingCycle);
//Serial.print (TrainingCycle);
Serial.printf (" Error = %f", Error);
// Serial.println (Error, 5);
toTerminal();
Serial.println ("\n");
Serial.println ("\n");
Serial.println ("Training Set Solved! ");
Serial.println ("--------");
Serial.println ("\n");
Serial.println ("\n");
ReportEvery1000 = 1;
/******************************************************************
* from a 7 segments input data predict the value
******************************************************************/
predict(&Input[3]);
}