home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8901.arc
/
NNPATM.ASC
< prev
next >
Wrap
Text File
|
1989-01-02
|
13KB
|
587 lines
_USING NEURAL NETWORKS FOR PATTERN RECOGNITION_
by Todd King
[LISTING ONE]
#include <stdio.h>
#define EXTERN extern
#include "neural.h"
/*-- MAKE_MIND ---------------------------------------
Constructs a mental unit with the given number
of input, hidden and output neurons.
------------------------------------------------------*/
make_mind(in, hid, out)
int in;
int hid;
int out;
{
if ( in > MAX_NEURONS ||
hid > MAX_NEURONS ||
out > MAX_NEURONS ) return(0);
if (in < 1 || hid < 1 || out < 1 ) return(0);
Mind.n_input = in;
Mind.n_hidden = hid;
Mind.n_output = out;
set_cluster_fun(NULL, NULL);
set_all_weights(1.0);
set_act_fun(pass);
set_user_in_fun(prompted);
set_result_fun(print_binary_state);
strcpy(Prompt.string, "Input a value for neuron %d: ");
Prompt.count = 1;
return(1);
}
/*-- ACTIVATE_MIND -----------------------------------------
Sets a mind in motion. Sequentially activating each neuron
-----------------------------------------------------------*/
activate_mind()
{
int i;
float net_input;
/* Activate input layer */
Prompt.count = 1;
for (i = 0; i < Mind.n_input; i++)
{
Mind.i_layer[i].value = Mind.user_in_fun();
}
/* Activate hidden layer */
for (i= 0; i < Mind.n_hidden; i++)
{
net_input = weighted_sum(i, HIDDEN);
Mind.h_layer[i].value = Mind.act_fun(net_input);
}
/* Activate feedback/certainty function (if one is set) */
if ( Mind.certainty != NULL) Mind.cluster_fun(Mind.certainty);
/* Activate output layer */
for (i=0; i < Mind.n_output; i++)
{
net_input = weighted_sum(i, OUTPUT);
Mind.o_layer[i].value = Mind.act_fun(net_input);
Mind.result_fun(Mind.o_layer[i].value);
}
}
/*-- SET_ALL_WEIGHTS --------------------------------------
Sets the weight of all connections between all neurons
in all layers to the given value
----------------------------------------------------------*/
set_all_weights(value)
float value;
{
int i, j;
/* Weights between input and hidden */
for(i = 0; i < Mind.n_input; i++)
{
for(j = 0; j < Mind.n_hidden; j++)
{
Input_to_hidden[i][j].weight = value;
}
}
/* Weights between hidden and output */
for(i=0; i< Mind.n_hidden; i++)
{
for(j = 0; j < Mind.n_output; j++)
{
Hidden_to_output[i][j].weight = value;
}
}
}
/*-- SET_WEIGHT -------------------------------------
Sets the weight between two neurons to a given value.
------------------------------------------------------*/
set_weight(from, to, layer, value)
int from;
int to;
int layer;
float value;
{
switch (layer)
{
case HIDDEN:
if (from > Mind.n_input) return;
if (to > Mind.n_hidden) return;
Input_to_hidden[from][to].weight = value;
break;
case OUTPUT:
if (from > Mind.n_hidden) return;
if (to > Mind.n_output) return;
Hidden_to_output[from][to].weight = value;
break;
default:
break;
}
return;
}
/*-- WEIGHT_SUM --------------------------------------------
Calculates the weighted sum for a given neuron in a given
layer
----------------------------------------------------------*/
float weighted_sum(this_neuron, this_layer)
int this_neuron;
int this_layer;
{
int i;
float sum = 0.0;
switch (this_layer)
{
case HIDDEN:
for (i = 0; i < Mind.n_input; i++)
{
sum += (Mind.i_layer[i].value * Input_to_hidden[i][this_neuron].weight);
}
break;
case OUTPUT:
for (i = 0; i < Mind.n_hidden; i++)
{
sum += (Mind.h_layer[i].value * Hidden_to_output[i][this_neuron].weight);
}
break;
default:
break;
}
return (sum);
}
/*-- PASS ----------------------------------------------
Returns the input value. A dummy activation function.
--------------------------------------------------------*/
float pass(value)
float value;
{
return (value);
}
/*-- PROMPTED ---------------------------------------
Prompts the user for an input value and returns the
value. A user input function.
-----------------------------------------------------*/
float prompted()
{
float value;
printf(Prompt.string, Prompt.count++);
scanf("%f", &value);
return(value);
}
/*-- PRINT_BINARY_STATE -------------------------------
Prints the output state of a neuron. If greater than
0.0 the value printed is "on", otherwise "off".
------------------------------------------------------*/
float print_binary_state(value)
float value;
{
printf("The output gate is: ");
if (value > 0.0) printf("ON.");
else printf("OFF.");
printf("\n");
}
[LISTING TWO]
/* Linear network */
#define EXTERN
#include "neural.h"
#define MEMBERS 5
float print_vote_state();
#define plural(x) (x == 1 ? "" : "s")
main()
{
int i;
make_mind(5,1,1);
set_result_fun(print_vote_state);
strcpy(Prompt.string, "Ballot for member %d: ");
for(i=0; i<MEMBERS; i++)
{
set_weight(i, 0, HIDDEN, (float)(i+1) );
}
printf("Ballot values: 1 = for, 0 = obstain, -1 = against\n\n");
activate_mind();
}
float print_vote_state(value)
float value;
{
int votes;
printf("The vote is: ");
votes = (int)value;
if (votes > 0)
printf("FOR, by %d vote%s", votes, plural(votes) );
else if (votes < 0)
printf("AGAINST, by %d vote%s", -votes, plural(-votes) );
else
printf("A TIE");
printf(".\n");
}
[LISTING THREE]
/* Simple linear threshold network.
Demonstates logic gates */
#define EXTERN
#include "neural.h"
float linear_threshold();
main()
{
int i;
/* OR gates work using the default weights (1.0) */
strcpy(Prompt.string, "Logic state of gate %d: ");
printf("Logic values: 1, on; 0, off\n\n");
printf("OR logic gate.\n");
printf("--------------\n\n");
make_mind(2, 1, 1);
activate_mind();
/* AND gates must have weights < 1.0 ( and > 0.0) */
printf("\n");
printf("AND logic gate.\n");
printf("--------------\n\n");
for(i = 0; i < 2; i++)
{
set_weight(i, 0, HIDDEN, 0.5);
}
activate_mind();
/* XOR gates are the most complicated */
printf("\n");
printf("XOR logic gate.\n");
printf("--------------\n\n");
make_mind(2, 2, 1);
set_weight(0, 0, HIDDEN, 1.0);
set_weight(1, 0, HIDDEN, -1.0);
set_weight(0, 1, HIDDEN, -1.0);
set_weight(1, 1, HIDDEN, 1.0);
set_weight(0, 0, OUTPUT, 1.0);
set_weight(1, 0, OUTPUT, 1.0);
set_act_fun(linear_threshold);
activate_mind();
}
/*-- LINEAR_THRESHOLD -------------------------------------
If the input value is greater than zero then it returns
1.0, otherwise it returns 0.0. A linear threshold
activation function.
----------------------------------------------------------*/
float linear_threshold(value)
float value;
{
if (value > 0.0) return(1.0);
else return(0.0);
}
[LISTING FOUR]
/*
Optical Character Recognition (OCR) neural network
This is a hybrid between a linear threshold, fully
interconnected network and a linear network. The
transition being at the hidden layer. A Feedback neuron
gaurantees a pattern match in the threshold layer.
*/
#include <stdio.h>
#define EXTERN
#include "neural.h"
float percep();
float print_ocr();
float certainty_cluster();
float Certainty;
FILE *Ocr_fptr;
main(argc, argv)
int argc;
char *argv[];
{
int i;
if(argc < 2)
{
printf("proper usage: ocr [<train_file> ...] [-test <test_file> ...]\n");
exit(-1);
}
make_mind(35, 3, 1);
set_user_in_fun(percep);
set_result_fun(print_ocr);
set_cluster_fun(certainty_cluster, &Certainty);
set_all_weights(0.0);
/* Teach the network about the patterns */
i = 1;
while(strcmp(argv[i], "-test") != 0)
{
printf("Learning: %s\n", argv[i]);
if( i > Mind.n_hidden)
{
printf("Too many pattern groups for the given topology, aborting.\n");
exit(-1);
}
ocr_learn(argv[i], i - 1);
i++;
if(i >= argc)
{
printf("Nothing to test - exiting\n");
exit(-1);
}
}
/* Classify each pattern based on what the network knows */
i++; /* Skip over "-test" deliniator */
while(i < argc)
{
printf("Testing %s\n", argv[i]);
if ((Ocr_fptr = fopen(argv[i], "r")) == NULL)
{
perror(argv[i]);
printf("Unable to open file, skipping pattern.\n");
i++;
continue;
}
activate_mind();
fclose(Ocr_fptr);
i++;
}
}
/*-- PERCEP ------------------------------------------------
Returns the value of the next pixel every time its called.
The pixel state is determined from the contents of the
pre-opened file pointed to by 'Ocr_fptr'.
----------------------------------------------------------*/
float percep()
{
extern FILE *Ocr_fptr;
int pixel_value;
fscanf(Ocr_fptr, "%1d", &pixel_value);
return( (float)pixel_value);
}
/*-- PRINT_OCR -------------------------------------
Prints the character which the network determines
it to be. Also prints the certainty of the match.
------------------------------------------------------*/
float print_ocr(value)
float value;
{
extern float Certainty;
printf("The character is '%c' (%d).\n", (int)value, (int)value);
printf("with a certainty of %3.2f%.\n", Certainty);
}
/*-- OCR_LEARN -----------------------------
Teach the network how to classify
a pattern.
--------------------------------------------*/
ocr_learn(filename, group_id)
char filename[];
int group_id;
{
int i;
FILE *fptr;
int pixel_cnt = 0;
int pixel_value;
float dist_weight;
float output_value;
if ((fptr = fopen(filename, "r")) == NULL)
{
perror(filename);
printf("Skipping pattern.\n");
return(0);
}
/* Determine the number of "on" pixels, hence fractional weight */
for(i=0; i < Mind.n_input; i++)
{
fscanf(fptr, "%1d", &pixel_value);
if(pixel_value == 1) pixel_cnt++;
}
dist_weight = 1.0/pixel_cnt;
rewind(fptr);
/* Set fractional weight for each "on" connection */
for(i=0; i < Mind.n_input; i++)
{
fscanf(fptr, "%1d", &pixel_value);
if(pixel_value == 1) set_weight(i, group_id, HIDDEN, dist_weight);
}
/* Now set weight for output value for this character */
fscanf(fptr, "%f", &output_value);
set_weight(group_id, 0, OUTPUT, output_value);
fclose(fptr);
return(1);
}
/*-- CERTAINTY_CLUSTER ------------------------------------
Performs a cluster function. It inhibits (sets to 0) all
neurons in the cluster except the one which is closest to
the value 1.0. This neuron is set to 1.0. The passed
variable is assigned the certainty to which the closest
neuron felt it matched the pattern
----------------------------------------------------------*/
float certainty_cluster(certainty)
float *certainty;
{
int i;
float highest = 0.0;
int closest = -1;
for(i=0; i<Mind.n_hidden; i++)
{
if(Mind.h_layer[i].value > highest)
{
closest = i;
highest = Mind.h_layer[i].value;
}
}
if(closest == -1) /* All are equally likely - choose the first */
{
closest = 0;
}
*certainty = Mind.h_layer[closest].value * 100.0;
/*
Cause just enough feedback to the neuron which is closest
to being "on" so that it is "on". That is set it "on"
All others are given negative feedback to force them to
zero. (set them to zero).
*/
for( i = 0; i < Mind.n_hidden; i++)
{
if (i == closest) Mind.h_layer[i].value = 1.0;
else Mind.h_layer[i].value = 0.0;
}
}
[LISTING FIVE]
#ifndef _NEURAL_
#define _NERUAL_
#define MAX_NEURONS 35
#define HIDDEN 1
#define OUTPUT 2
/* Type definition for neurons and neural networks */
typedef struct {
float value;
} NEURON;
typedef struct {
int n_input;
int n_hidden;
int n_output;
float *certainty;
float (*cluster_fun)();
float (*act_fun)();
float (*user_in_fun)();
float (*result_fun)();
NEURON i_layer[MAX_NEURONS];
NEURON h_layer[MAX_NEURONS];
NEURON o_layer[MAX_NEURONS];
} MIND;
typedef struct {
float weight;
} WEIGHTS;
typedef struct
{
char string[80];
int count;
} PROMPT;
/* Global Variables */
EXTERN MIND Mind;
EXTERN WEIGHTS Input_to_hidden[MAX_NEURONS][MAX_NEURONS];
EXTERN WEIGHTS Hidden_to_output[MAX_NEURONS][MAX_NEURONS];
EXTERN PROMPT Prompt;
/* Functions */
float weighted_sum();
float pass();
float prompted();
float print_binary_state();
float certainty_fun();
int activate_mind();
/* Pseudo-functions */
#define set_act_fun(f) Mind.act_fun = f
#define set_user_in_fun(f) Mind.user_in_fun = f
#define set_back_prop_fun(f) Mind.back_prop_fun = f
#define set_result_fun(f) Mind.result_fun = f
#define set_cluster_fun(f, x) Mind.cluster_fun = f; Mind.certainty = x
#endif
[LISTING SIX]
Board:
board.c (neural.h)
neurlib.c (neural.h)
Logic:
logic.c (neural.h)
neurlib.c (neural.h)
OCR:
ocr.c (neural.h)
neurlib.c (neural.h)