Newsgroups: comp.ai.neural-nets
Path: cantaloupe.srv.cs.cmu.edu!bb3.andrew.cmu.edu!newsfeed.pitt.edu!gatech!newsfeed.internetmci.com!howland.reston.ans.net!EU.net!peer-news.britain.eu.net!newsfeed.ed.ac.uk!dcs.ed.ac.uk!flugga.dcs.ed.ac.uk!iic
From: iic@dcs.ed.ac.uk (Ian Clarke)
Subject: The C Neural Network Toolkit-Update 1
X-Nntp-Posting-Host: flugga.dcs.ed.ac.uk
Message-ID: <DL0MGt.68s.0.staffin.dcs.ed.ac.uk@dcs.ed.ac.uk>
Sender: iic@flugga.dcs.ed.ac.uk (Ian Clarke)
Organization: Department of Computer Science, University of Edinburgh
X-Newsreader: xrn 8.00
Date: Thu, 11 Jan 1996 11:55:38 GMT
Lines: 332

Here you will find the CNNTK1.C file followed by a brief document
which should help anyone understand how it works.  Watch this space for
futher additions/amendments/example programs.  Email me with comments

Ian   

iic@dcs.ed.ac.uk


cnntk1.c>

/*
  The C Neural Network Toolkit - Include File
  (c) 1993,1994 Ian Clarke
  See 'legal.doc' in 'documnts.fld' folder for legal information
*/
#define train teach

struct node
{
 float error,input,output,correct_output,threshold,change_in_threshold;
 short type;
};

const signed short input=-1;
const signed short hidden=0;
const signed short output=1;

struct connection
{
 short start,end;
 float weight,change_in_weight;
};


/* Procedure prototypes */

void run_net(struct node *nodes,struct connection *conns,int n,int c);
float af(float value);
void reset_net(struct node *nodes,struct connection *conns,int n,int c);
void teach_net(struct node *nodes,struct connection *conns,int n,int c
               ,float learning_rate);
float derror(float,float);
void scramble_net(struct node *nodes,struct connection *conns,int n,int c);
void make_changes(struct node *nodes,struct connection *conns,int n,int c);
/* This procedure causes the energy to flow from the bottom of
   the net to the top*/
   
void run_net(struct node nodes[],struct connection conns[],int n,int c)
{
 int x;

 for (x=0;x<n;x++)
 {
  nodes[x].input=0;
 };

 for (x=0;x<c;x++)
 {
  if ((nodes[conns[x].start].output==0)&(nodes[conns[x].start].type!=input))
  {
   nodes[conns[x].start].output=af(nodes[conns[x].start].input+nodes[conns[x].start].threshold);
  };
  nodes[conns[x].end].input+=nodes[conns[x].start].output*conns[x].weight;
  nodes[conns[x].end].output=0;
 };
 for(x=n-1;nodes[x].type==output;x--)
 {
  nodes[x].output=af(nodes[x].input+nodes[x].threshold);
 };
} 

/* This is the function used to determine the response of a node to input*/

float af(float input)
{
 float output;
 output=(float) (1/(1+exp(-input)));
 return output;
}

/* Reset 'change_in_weight' and 'change_in_threshold' */

void reset_net(struct node nodes[],struct connection conns[],int n,int c)
{
 int counter;
 for (counter=0;counter<n;counter++)
 {
  nodes[counter].change_in_threshold=0;
 };
 for (counter=0;counter<=c-1;counter++)
 {
  conns[counter].change_in_weight=0;
 };
}

/* Teach net */

void teach_net(struct node nodes[],struct connection conns[],int n,int c,float lr)
{
 int x;
 for(x=0;x<n;x++)
 {
  nodes[x].error=0;
 };
 for(x=c-1;x>-1;x--)
 {
  if (nodes[conns[x].end].type==output)
  {
   nodes[conns[x].end].error=nodes[conns[x].end].correct_output-
   nodes[conns[x].end].output;
  };
  nodes[conns[x].start].error+=conns[x].weight*
  derror(nodes[conns[x].end].error,nodes[conns[x].start].output);
 };
 for(x=0;x<c;x++)
 {
  conns[x].change_in_weight+=lr*nodes[conns[x].start].output*
  derror(nodes[conns[x].end].error,nodes[conns[x].end].output);
 };
 for(x=0;x<n;x++)
 {
  nodes[x].change_in_threshold+=derror(nodes[x].error,nodes[x].output);
 };
}

float derror(float error,float output)
{
 float otpt;
 otpt=error*output*(1-output);
 return otpt;
}

void make_changes(struct node nodes[],struct connection conns[],int n,int c)
{
 int x;
 for(x=0;x<n;x++)
 {
  nodes[x].threshold+=nodes[x].change_in_threshold;
 };
 for(x=0;x<c;x++)
 {
  conns[x].weight+=conns[x].change_in_weight;
 };
}

void scramble_net(struct node nodes[],struct connection conns[],int n,int c)
{
 int p;
 for(p=0;p<n;p++)
 {
  nodes[p].change_in_threshold=0;
  nodes[p].threshold=((int) drand48()*4)-2;
 };
 for(p=0;p<c;p++)
 {
  conns[p].change_in_weight=0;
  conns[p].weight=((int) drand48()*4)-2;
 };
}


cnntk1.doc>


                        The C Neural Network Tool-Kit
                                    Design
                                 By Ian Clarke

NOTE: This is a hastily prepared guide to the use of the C Neural
Network toolkit, I expect it to be full of errors so please email me
when you find them.

Email: iic@dcs.ed.ac.uk

****************Intended use of the C Neural Network Toolkit*******************

The C Neural Network Tool-Kit (CNNTK) is an assortment of functions,
designed to allow any C programmer to use the power of Neural Networks in
his or her programs.  The program will include detailed documentation to
allow the user to learn about neural networks, they will not even need to
know what a neural network is before they read the instruction files!

***************************Technical Specifications****************************

CNNTK is fully ANSI compatible, allowing it to be used under any operating
system with a ANSI C compiler.  The type of network modelled is a
multi-layer feed-forward net, using the generalised delta, or backward
error propogation learning algorithm.  The program would heavily benifit
from a maths co-processor if available(and if the compiler used can detect
and make use of it).

*********************************Background************************************

CNNTK was developed using Lattice C V5.52 on an Atari ST/Falcon computer.
Also available is a program 'The Neural Network Construction Kit', by the
same author, but currently available for the Atari ST/TT/Falcon range of
computers only.

*******************************Internal Design*********************************

The Neural Network is contained within 2 arrays.

The first array is of 'node' structures.  The node structure contains
the following elements:

*float output
This element contains the output of the node in question, this will
contain the output of output nodes, and should be set to the input of
input nodes

*short type
This contains the type of the node, use the constants input, hidden or
output to set this to the correct value

*float correct_output
This should contain the correct output of a node, ie. what the node
should output.  This should be set before teach_net is called.

float error
This is for the learning algorithm and need not be touched by the user

float threshold
This is the nodes threshold, and need not be touched by the user

float input
This is the input to a node, DON'T USE THIS TO SET THE INPUT OF INPUT
NODES, float output SHOULD BE USED INSTEAD


The second array is of 'connection' structures and contains
information concerning the connections.

*short start
This is the node at which the connection starts

*short end
This is the node at which the connection ends

short weight
This is the weight of the connection and need not be touched by the user

short change_in_weight
This is used by the training algorithm and need not be touched by the
user

     *****************************Functions*******************************

The high level functions (in contact with the users program) are:

*NODE is a pointer to an array of node structures
*CONNECTION is a pointer to an array of connection structures
NODES is the amount of nodes
CONNECTIONS is the amount of connections

RUN_NET(*NODE,*CONNECTION,NODES,CONNECTIONS)
 This function will run through one cycle of the neural network and set the
 output of the output nodes( NODE[x].output ) according to the output of the
 input nodes (also NODE [x].output )
TEACH_NET(*NODE,*CONNECTION,NODES,CONNECTIONS,LEARNING_RATE)
 This function will adjust the weights of the connections and thresholds
 of the nodes to bring the actual output( NODE[x].output ) of the output
 nodes, closer to the desired output( NODE[x].correct_output )
SCRAMBLE_NET(*NODE,*CONNECTION,NODES,CONNECTIONS)
 This resets connection weights and node thresholds to random values
MAKE_CHANGES(*NODE,*CONNECTION,NODES,CONNECTIONS)
This is called after one training cycle to implement the changes in
weights and thresholds which have been calculated during the training
cycle.
RESET_NET(*NODE,*CONNECTION,NODES,CONNECTIONS)
 After make_changes has been called, this must be called to reset the
change_in_weight and change_in_threshold values




What follows is the general structure of a CNNTK program

1)#include "cnntk1.c"  >Include C Neural Network Toolkit File

Define node and connection arrays (normally global)

2)Set up connections between nodes  (by setting .start and .end values
in connection structures

3)Set types of nodes (by setting .type component of node structures to
hidden, input or output (these are defined in cnntk1.c)

4)Call scramble_net

Training Cycle>>

5)Set .output values of input nodes to first/next item of input data

6)Set .correct_output values of output nodes

7)Call run_net

8)Call teach_net

9)If not last item of input data return to 5)

10) Call make_changes to implement changes

11) If not last training cycle return to stage 5)

To run the net>

1) Set .output values of input nodes to first/next item of input data

2) Call run_net

3) Output of net will be in .output of output nodes

4) If not last item of input data return to stage 1)













-- 
|IAN CLARKE        I.Clarke@sms.ed.ac.uk "They couldn't hit an elephant|
|                  iic@dcs.ed.ac.uk      at this dist.."  - Last words |
|I.Clarke@ed.ac.uk ianc@aisb.ed.ac.uk    of General M Howard, 1918     |
