TriuneCadence/THES/BP_UNIT.PP

1850 lines
57 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

UNIT BP_unit;
{
This Unit implements the necessary functions for modelling back-
propagation artificial neural network architectures.
}
{
Copyright 1989 by Wesley R. Elsberry. All rights reserved.
Commercial use of this software is prohibited without written consent of
the author.
For information, bug reports, and updates contact
Wesley R. Elsberry
528 Chambers Creek Drive South
Everman, Texas 76140
Telephone: (817) 551-7018
}
INTERFACE
USES
DOS, Struct, ANN;
CONST
mach_inf = 1E37;
exp_max = 80.0;
TAB = ^I;
Debug : BOOLEAN = FALSE;
TYPE
REAL = SINGLE;
file_string_ = STRING;
node_type_ = (Input,hidden,Output);
weight_ptr_ = ^weight_;
weight_ = RECORD
w, dw : REAL;
END;
vector_node_ptr_ = ^vector_node_;
vector_node_ = RECORD
V : REAL;
END;
sptr_ = ^STRING;
data_rec_ptr_ = ^data_rec_;
data_rec_ = RECORD
s : sptr_;
n : data_rec_ptr_;
END;
weight_node_ptr_ = ^weight_node_;
weight_node_ = RECORD
connect : BOOLEAN;
w, dw, ldw : REAL;
END;
BP_net_ptr_ = ^BP_net_;
BP_node_ptr_ = ^BP_node_;
BP_net_ = RECORD
vs, ve : DVE_ptr_; {node vector start and vector end}
ws : DVE_ptr_; {weight array}
learning_rate : REAL;
alpha : REAL; {factor for momentum term}
vi : DVE_ptr_; {input vector}
vos, voe : DVE_ptr_; {output vector}
vts, vte : DVE_ptr_; {training vector}
n_input, n_hidden, n_output : WORD;
maxerr : REAL;
errtol : REAL;
data_fname : file_string_;
data_f : TEXT;
training_iterations : INTEGER;
out_fname : file_string_;
out_f : TEXT;
wt_fname : file_string_;
wt_f : TEXT;
END;
BP_node_ = RECORD
nt : node_type_; {Input, hidden, or output}
loc : WORD;
ni : REAL; {net input value}
delta : REAL; {delta value for node}
base : REAL;
range : REAL;
theta : REAL;
dtheta, ldtheta : REAL;
fw, bw : DVE_ptr_; {points to entries in weight_matrix}
END;
PROCEDURE Dump_BP_net_weights
(VAR BPN : BP_net_; VAR Fname : STRING);
{Save weights and node bias unit values to a file}
PROCEDURE Set_BP_net_weights_from_file
(VAR BPN : BP_net_; VAR Fname : STRING);
{Restore weights and node bias unit values from a file}
PROCEDURE BP_set_net_connects_from_file
(VAR BPN : BP_net_; VAR Fname : STRING);
{Sets network connectivity values from a file}
PROCEDURE Setup_BP_net
(VAR BPN : BP_net_;VAR Fname : STRING);
{Get data values from a text file to set up basic BP constants, sizes, and
other necessary information, or query user if filename is not valid.}
PROCEDURE Set_Input_vector_from_file
(VAR BPN : BP_net_);
{Get data values from a text file to fill input vector.}
PROCEDURE Set_Training_vector_from_file
(VAR BPN : BP_net_);
{Get data values from a text file to fill training vector.}
PROCEDURE BP_Feed_forward
(VAR BPN : BP_net_);
{Present values to network and propagate values forward, set the output
vector.}
PROCEDURE BP_train_presentation
(VAR BPN : BP_net_);
{Present values to network, propagate forward, set output, compare output
to training, back-propagate, collect statistics but do not change weights.}
PROCEDURE BP_train_and_change
(VAR BPN : BP_net_);
{Present values to network, propagate forward, set output, compare output
to training, back-propagate, collect statistics, change weights, and reset
statistic variables.}
PROCEDURE BP_change
(VAR BPN : BP_net_);
{Change weights using current statistics and reset statistics.}
PROCEDURE BP_dump_net
(VAR BPN : BP_net_);
{Dump net parameters, node activities, and weights for inspection.}
FUNCTION BP_net_error
(VAR BPN : BP_net_):REAL;
{Returns the largest error from the output nodes}
PROCEDURE Display_weights
(BPN : BP_net_);
{Display of the current weight values for the network}
{----------------------------------------------------------------------}
IMPLEMENTATION
{----------------------------------------------------------------------}
{Private, internal functions}
FUNCTION max (r1, r2 : REAL):REAL;
BEGIN
IF r1 >= r2 THEN max := r1
ELSE max := r2;
END;
{----------------------------------------------------------------------}
PROCEDURE Dump_BP_net_weights (VAR BPN : BP_net_;
VAR Fname : STRING);
{Save weights and node bias unit values to a file}
{
Preface vector length with !V
Preface weight vectors with !W
Preface bias unit vector with !T
}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii, jj, m, n : WORD;
inch : CHAR;
done : BOOLEAN;
tp1 : DVE_ptr_;
ss : STRING;
BEGIN
n := BPN.n_input + BPN.n_hidden + BPN.n_output;
(*
ss := FSEARCH(Fname,GETENV('PATH'));
IF LENGTH(ss) = 0 THEN BEGIN
WRITELN('**ERROR** File does not exist');
EXIT;
END; *)
BPN.wt_fname := Fname;
Assign(BPN.wt_f,Fname);
Rewrite(BPN.wt_f);
done := FALSE;
{Write vector length}
Writeln(BPN.wt_f,'!V ',n:1);
FOR jj := 1 TO n DO BEGIN
Write(BPN.wt_f,'!W ');
FOR ii := 1 TO n DO BEGIN
tp1 := Find_element_matrix(ii,jj,BPN.ws);
IF wnp_(tp1^.dptr)^.connect THEN Write(BPN.wt_f,wnp_(tp1^.dptr)^.w:
4:4,' ')
ELSE Write(BPN.wt_f,0.0:4:4,' ');
END;
Writeln(BPN.wt_f);
END;
Write(BPN.wt_f,'!T ');
FOR ii := 1 TO n DO BEGIN
tp1 := Find_element_DVE(ii,BPN.vs);
Write(BPN.wt_f,bpnp_(tp1^.dptr)^.theta:4:4,' ');
END;
Writeln(BPN.wt_f);
Writeln(BPN.wt_f,'!Z ');
Close(BPN.wt_f);
END; {Dump_BP_net_weights}
PROCEDURE Set_BP_net_weights_from_file (VAR BPN : BP_net_;
VAR Fname : STRING);
{Restore weights and node bias unit values from a file}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii, jj, m, n : WORD;
rr : REAL;
tp1, wp1, wp2 : DVE_ptr_;
inch : CHAR;
done : BOOLEAN;
ss : STRING;
BEGIN {}
n := BPN.n_input + BPN.n_hidden + BPN.n_output;
ss := FSEARCH (Fname,GETENV('PATH'));
IF (Length(ss) = 0) THEN BEGIN
Writeln ('**ERROR** File does not exist');
EXIT;
END;
Assign (BPN.wt_f,ss);
Reset (BPN.wt_f);
done := FALSE;
{Find vector length, compare to net vector length}
REPEAT
REPEAT {find command}
Read (BPN.wt_f,inch);
UNTIL (inch = '!') OR Eof(BPN.wt_f);
{}
Read (BPN.wt_f,inch);
UNTIL (UpCase (inch) = 'V') OR Eof (BPN.wt_f);
IF Eof (BPN.wt_f) THEN BEGIN
EXIT;
END;
Read (BPN.wt_f,inch);
Read (BPN.wt_f,m);
IF (m <> n) THEN BEGIN {Vector lengths don't match, quit}
EXIT;
END;
wp1 := BPN.ws;
REPEAT {get net params}
REPEAT {find command}
Read (BPN.wt_f,inch);
UNTIL (inch = '!'); {}
Read (BPN.wt_f,inch);
CASE UpCase (inch) OF
'T' : BEGIN {get bias values}
Read (BPN.data_f, inch);
FOR ii := 1 TO n DO BEGIN
tp1 := Find_element_DVE (ii,BPN.vs);
Read (BPN.wt_f,rr);
bpnp_(tp1^.dptr)^.theta := rr;
END;
END; {}
'W' : BEGIN {get weights}
IF wp1 <> NIL THEN BEGIN
Read (BPN.data_f,inch);
FOR ii := 1 TO n DO BEGIN
wp2 := Find_element_DVE (ii,wp1);
Read (BPN.wt_f,rr);
wnp_(wp2^.dptr)^.w := rr;
END; {For ii}
wp1 := wp1^.down;
END;
END; {}
'Z' : DONE := TRUE;
ELSE
BEGIN
DONE := TRUE;
END;
END;
UNTIL (done OR Eof (BPN.wt_f));
{}
END; {set_BP_net_weights_from_file}
PROCEDURE BP_set_net_connects_from_file (VAR BPN : BP_net_;
VAR Fname : STRING);
{Sets network connectivity values from a file}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii, jj, kk, m, n : WORD;
tp1, wp1, wp2 : DVE_ptr_;
inch : CHAR;
done : BOOLEAN;
ss : STRING;
cfile : TEXT;
BEGIN {}
n := BPN.n_input + BPN.n_hidden + BPN.n_output;
ss := FSEARCH (Fname,GETENV('PATH'));
IF (Length(ss) = 0) THEN BEGIN
Writeln ('**ERROR** File does not exist');
EXIT;
END;
Assign (cfile,ss);
Reset (cfile);
done := FALSE;
{Find vector length, compare to net vector length}
REPEAT
REPEAT {find command}
Read (cfile,inch);
UNTIL (inch = '!') OR Eof(cfile);
{}
Read (cfile,inch);
UNTIL (UpCase (inch) = 'V') OR Eof (cfile);
IF Eof (cfile) THEN BEGIN
EXIT;
END;
Read (cfile,inch);
Read (cfile,m);
IF (m <> n) THEN BEGIN {Vector lengths don't match, quit}
EXIT;
END;
wp1 := BPN.ws;
REPEAT {get net params}
REPEAT {find command}
Read (cfile,inch);
UNTIL (inch = '!'); {}
Read (cfile,inch);
CASE UpCase (inch) OF
'C' : BEGIN {get weights}
IF wp1 <> NIL THEN BEGIN
Read (cfile,inch);
FOR ii := 1 TO n DO BEGIN
wp2 := Find_element_DVE (ii,wp1);
Read (cfile,kk);
wnp_(wp2^.dptr)^.connect := (kk = 1);
END; {For ii}
wp1 := wp1^.down;
END;
END; {}
'Z' : DONE := TRUE;
ELSE
BEGIN
DONE := TRUE;
END;
END;
UNTIL (done OR Eof (cfile));
{}
END; {BP_set_net_connects_from_file}
PROCEDURE Dump_node (net : BP_net_;
node : BP_node_ptr_);
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
BEGIN
IF (debug) THEN {}
BEGIN
Writeln ('DUMP_NODE');
Writeln (NET.OUT_F,'DUMP_NODE');
END;
IF (node <> NIL) THEN BEGIN
CASE node^.nt OF
Input : BEGIN
Write (net.out_f,'INPUT');
Write ('INPUT');
END;
hidden : BEGIN
Write (net.out_f,'HIDDEN');
Write ('HIDDEN');
END;
Output : BEGIN
Write (net.out_f,'OUTPUT');
Write ('OUTPUT');
END;
END;
Write (net.out_f,tab,'LOC : ',NODE^.LOC);
Write ('LOC : ',NODE^.LOC);
Writeln (net.out_f,tab,'ADDR : ',Seg(NODE),':',Ofs(NODE));
Writeln (tab,'ADDR : ',Seg(NODE),':',Ofs(NODE));
Write (net.out_f,'NI : ',node^.ni:8);
Write ('NI : ',node^.ni:8);
Writeln (net.out_f,tab,'DELTA : ',NODE^.DELTA:8);
Writeln (tab,'DELTA : ',NODE^.DELTA:8);
Write (net.out_f,'BASE : ',NODE^.BASE:8);
Write ('BASE : ',NODE^.BASE:8);
Writeln (net.out_f,tab,'RANGE : ',NODE^.RANGE:8);
Writeln (tab,'RANGE : ',NODE^.RANGE:8);
Write (net.out_f,'THETA : ',NODE^.THETA:8);
Write ('THETA : ',NODE^.THETA:8);
Writeln (net.out_f,tab,'DTHETA : ',NODE^.DTHETA:8,tab,
'LDTHETA : ',
NODE^.LDTHETA:8);
Writeln (tab,'DTHETA : ',NODE^.DTHETA:8,tab,'LDTHETA : ',NODE^.
LDTHETA:8);
Writeln (net.out_f,'FW : ',Seg(NODE^.FW),':', Ofs(NODE^.FW),
tab,'BW : ', Seg(NODE^.BW),':',Ofs(NODE^.BW));
Writeln ('FW : ',Seg(NODE^.FW),':', Ofs(NODE^.FW),tab,'BW : ',
Seg(NODE^.BW),':',Ofs(NODE^.BW));
Writeln (net.out_f);
Writeln;
END;
IF (debug) THEN BEGIN
Writeln ('END DUMP_NODE');
Writeln (NET.OUT_F,'END DUMP_NODE');
END;
END;
PROCEDURE Display_weights (BPN : BP_net_);
{Display of the current weight values for the network}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
twpd, twpa : DVE_ptr_;
wptr : DVE_ptr_;
BEGIN {}
IF debug THEN BEGIN
Writeln ('DISPLAY_WEIGHTS');
Writeln (BPN.OUT_F,'DISPLAY_WEIGHTS');
END;
twpd := BPN.ws;
twpa := BPN.ws;
WHILE (twpd <> NIL) DO BEGIN{}
WHILE (twpa <> NIL) DO BEGIN
{}
wptr := twpa^.dptr;
IF (wnp_(wptr)^.connect) THEN BEGIN
Write (BPN.out_f,wnp_(wptr)^.w:5:1,' ');
Write (wnp_(wptr)^.w:5:1,' ');
END
ELSE {}
BEGIN
Write (BPN.out_f,' --- ');
Write (' --- ');
END;
twpa := twpa^.right;
END; {}
Writeln (BPN.out_f);
Writeln ;
twpd := twpd^.down;
twpa := twpd;
END; {}
Writeln (BPN.out_f,'End of weights');
Writeln ('End of weights');
Writeln;
Writeln;
IF (debug) THEN {}
BEGIN
Writeln ('END DISPLAY_WEIGHTS');
Writeln (BPN.OUT_F,'END DISPLAY_WEIGHTS');
END;
Flush (BPN.out_f);
END; {}
PROCEDURE Display_Vector (vp : DVE_ptr_;
N : INTEGER;
NET : BP_net_);
{}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii : INTEGER;
vptr : vector_node_ptr_;
BEGIN {}
IF debug THEN BEGIN
Writeln ('DISPLAY_VECTOR');
Writeln (NET.OUT_F,'DISPLAY_VECTOR');
END;
FOR II := 1 TO N DO BEGIN {}
vptr := vp^.dptr;
Write (net.out_f,vptr^.V:8,' ');
Write (vptr^.V:8,' ');
vp := vp^.right;
END;
Writeln (net.out_f);
Writeln;
IF (debug) THEN {}
BEGIN
Writeln ('END DISPLAY_VECTOR');
Writeln (NET.OUT_F,'END DISPLAY_VECTOR');
END;
END; {}
FUNCTION BP_net_error (VAR BPN : BP_net_):REAL;
{Returns the largest error from the output nodes}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
rr : REAL;
tp, vp1, vp2 : DVE_ptr_;
ii, n : INTEGER;
BEGIN
rr := 0;
n := BPN.n_input + BPN.n_hidden + BPN.n_output;
vp1 := BPN.vos;
vp2 := BPN.vts;
FOR ii := 1 TO BPN.n_output DO BEGIN
IF (vp1^.dptr <> NIL) AND (vp2^.dptr <> NIL) THEN BEGIN
rr := max (ABS(rr),
ABS(vnp_(vp2^.dptr)^.v - vnp_(vp1^.dptr)^.v));
IF vp1^.right <> NIL THEN vp1 := vp1^.right;
IF vp2^.right <> NIL THEN vp2 := vp2^.right;
END
ELSE BEGIN
END;
END;
BP_net_error := ABS(rr);
END;
PROCEDURE Allocate_IO_vectors (VAR net : BP_net_);
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii, N : WORD;
BEGIN
IF debug THEN BEGIN
Writeln ('ALLOCATE_IO_VECTORS');
Writeln (NET.OUT_F,'ALLOCATE_IO_VECTORS');
END;
N := net.n_input + net.n_hidden + net.n_output;
net.vi := Create_DVE_vector (net.n_input, SizeOf(vector_node_));
net.vos := Create_DVE_vector (net.n_output, SizeOf(vector_node_));
net.vts := Create_DVE_vector (net.n_output, SizeOf(vector_node_));
net.voe := Find_element_DVE (net.n_output, net.vos);
net.vte := Find_element_DVE (net.n_output, net.vts);
IF (debug) THEN {}
BEGIN
Writeln ('END ALLOCATE_IO_VECTORS');
Writeln (NET.OUT_F,'END ALLOCATE_IO_VECTORS');
END;
END;
PROCEDURE Allocate_node_vector (VAR net : BP_net_);
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii, cnt, N : INTEGER;
Temp : BP_node_ptr_;
nptr : DVE_ptr_;
low, high : REAL;
ns : BP_node_;
BEGIN
cnt := 1;
N := net.n_input + net.n_hidden + net.n_output;
IF debug THEN BEGIN
Writeln ('ALLOCATE_NODE_VECTOR');
Writeln (NET.OUT_F,'ALLOCATE_NODE_VECTOR');
END;
net.vs := Create_DVE_vector (net.n_input, SizeOf (BP_node_));
net.ve := Find_element_DVE (net.n_input, net.vs);
nptr := net.vs;
FOR ii := 1 TO net.n_input DO BEGIN
temp := nptr^.dptr;
Temp^.loc := cnt;
cnt := cnt + 1;
Temp^.nt := Input; {set node type}
Temp^.ni := 0; {init net input}
Temp^.fw := NIL; {no weight yet}
Temp^.bw := NIL; {no weight yet}
Temp^.delta := 0;
Temp^.base := 0;
Temp^.range := 1;
Temp^.theta := 0;
Temp^.dtheta := 0;
Temp^.ldtheta := 0;
nptr := nptr^.right;
END; {FOR}
net.ve^.right := Create_DVE_vector (net.n_hidden,
SizeOf(BP_node_));
net.ve^.right^.left := net.ve;
nptr := net.ve^.right;
net.ve := Find_element_DVE (net.n_input + net.n_hidden, net.vs);
FOR II := 1 TO net.n_hidden DO BEGIN
temp := nptr^.dptr;
Temp^.loc := cnt;
cnt := cnt + 1;
Temp^.nt := hidden; {set node type}
Temp^.ni := 0; {init net input}
Temp^.fw := NIL; {no weight yet}
Temp^.bw := NIL; {no weight yet}
Temp^.delta := 0;
Temp^.base := 0;
Temp^.range := 1;
Temp^.theta := gaussian_noise (0,0.25);
Temp^.dtheta := 0;
Temp^.ldtheta := 0;
nptr := nptr^.right;
END;
net.ve^.right := Create_DVE_vector (net.n_output,
SizeOf(BP_node_));
net.ve^.right^.left := net.ve;
nptr := net.ve^.right;
net.ve := Find_element_DVE (net.n_input + net.n_hidden
+ net.n_output,net.vs);
FOR II := 1 TO net.n_output DO BEGIN
temp := nptr^.dptr;
Temp^.loc := cnt;
cnt := cnt + 1;
Temp^.nt := Output; {set node type}
Temp^.ni := 0; {init net input}
Temp^.fw := NIL; {no weight yet}
Temp^.bw := NIL; {no weight yet}
Temp^.delta := 0;
Temp^.base := 0 {low};
Temp^.range := 1 {high - low};
Temp^.theta := gaussian_noise (0,0.25);
Temp^.dtheta := 0;
Temp^.ldtheta := 0;
nptr := nptr^.right;
END;
IF (debug) THEN BEGIN
Writeln ('END ALLOCATE_NODE_VECTOR');
Writeln (NET.OUT_F,'END ALLOCATE_NODE_VECTOR');
END;
END;
PROCEDURE Allocate_weight_matrix (VAR net : BP_net_);
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii, jj, N : WORD;
temp : DVE_ptr_;
tl, tc, tls, tcs : weight_node_ptr_;
Vt : Vector_node_ptr_;
cnt : INTEGER;
BEGIN
IF debug THEN BEGIN
Writeln ('ALLOCATE_WEIGHT_MATRIX');
Writeln (NET.OUT_F,'ALLOCATE_WEIGHT_MATRIX');
END;
cnt := 1;
N := net.n_input + net.n_hidden + net.n_output;
net.ws := create_matrix (n,n,SizeOf(weight_node_));
FOR ii := 1 TO n DO BEGIN
FOR jj := 1 TO n DO BEGIN
temp := Find_element_matrix(ii, jj, net.ws);
IF temp <> NIL THEN BEGIN
wnp_(temp^.dptr)^.connect := FALSE;
wnp_(temp^.dptr)^.w := 2 * Random - 1;
{random weights, -1 < w < 1 }
wnp_(temp^.dptr)^.dw := 0;
wnp_(temp^.dptr)^.ldw := 0;
END; {IF temp <> NIL}
END;
END;
IF (debug) THEN {}
BEGIN
Writeln ('END ALLOCATE_WEIGHT_MATRIX');
Writeln (NET.OUT_F,'END ALLOCATE_WEIGHT_MATRIX');
END;
END;
PROCEDURE Link_weights_to_nodes (VAR net : BP_net_);
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
Start, TempD, TempA : DVE_ptr_;
Vt : DVE_ptr_;
ii, jj, N : INTEGER;
BEGIN
{Link to node vector}
IF debug THEN BEGIN
Writeln ('LINK_WEIGHTS_TO_NODES');
Writeln (NET.OUT_F,'LINK_WEIGHTS_TO_NODES');
END;
N := net.n_input + net.n_hidden + net.n_output;
Start := net.ws;
TempD := Start;
TempA := Start;
Vt := net.vs;
FOR ii := 1 TO N DO BEGIN
bpnp_(Vt^.dptr)^.fw := TempD;
TempD := TempD^.down;
bpnp_(Vt^.dptr)^.bw := TempA;
TempA := TempA^.right;
Vt := Vt^.right;
END;
IF (debug) THEN {}
BEGIN
Writeln ('END LINK_WEIGHTS_TO_NODES');
Writeln (NET.OUT_F,'END LINK_WEIGHTS_TO_NODES');
END;
END; {Link_weights_to_nodes}
PROCEDURE Display_node_type (VAR net : BP_net_);
{}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
tp : DVE_ptr_;
N, ii : INTEGER;
BEGIN {}
IF debug THEN BEGIN
Writeln ('DISPLAY_NODE_TYPE');
Writeln (NET.OUT_F,'DISPLAY_NODE_TYPE');
END;
tp := net.vs;
N := net.n_input + net.n_hidden + net.n_output;
FOR ii := 1 TO n DO BEGIN {}
CASE bpnp_(tp^.dptr)^.nt OF
Input : BEGIN
Write (net.out_f,'I');
Write ('I');
END;
hidden : BEGIN
Write (net.out_f,'H');
Write ('H');
END;
Output : BEGIN
Write (net.out_f,'O');
Write ('O');
END;
END;
TP := tp^.right;
END; {}
Writeln (net.out_f);
Writeln ;
IF (debug) THEN {}
BEGIN
Writeln ('END DISPLAY_NODE_TYPE');
Writeln (NET.OUT_F,'END DISPLAY_NODE_TYPE');
END;
END; {}
PROCEDURE Display_node_deltas (VAR net : BP_net_);
{}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
tp : DVE_ptr_;
N, ii : INTEGER;
BEGIN {}
IF debug THEN BEGIN
Writeln ('DISPLAY_NODE_DELTAS');
Writeln (NET.OUT_F,'DISPLAY_NODE_DELTAS');
END;
tp := net.vs;
N := net.n_input + net.n_hidden + net.n_output;
FOR ii := 1 TO n DO BEGIN {}
TP := tp^.right;
END; {}
IF (debug) THEN {}
BEGIN
Writeln ('END DISPLAY_NODE_DELTAS');
Writeln (NET.OUT_F,'END DISPLAY_NODE_DELTAS');
END;
END; {}
PROCEDURE set_connectivity (VAR net : BP_net_);
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
wpt : DVE_ptr_;
tvd, tva : DVE_ptr_;
ii, jj, n : INTEGER;
BEGIN
IF debug THEN BEGIN
Writeln ('SET_CONNECTIVITY');
Writeln (NET.OUT_F,'SET_CONNECTIVITY');
END;
n := net.n_input + net.n_hidden + net.n_output;
tvd := net.vs; {beginning of node vector}
tva := net.vs;
wpt := bpnp_(tvd^.dptr)^.fw;
{display_node_type (net);}
FOR ii := 1 TO n DO BEGIN
FOR jj := 1 TO n DO BEGIN
CASE bpnp_(tvd^.dptr)^.nt OF
Input : BEGIN
wnp_(wpt^.dptr)^.connect := FALSE;
END;
hidden : BEGIN
IF (bpnp_(tva^.dptr)^.nt = Input) THEN BEGIN
wnp_(wpt^.dptr)^.connect := TRUE;
END
ELSE BEGIN
wnp_(wpt^.dptr)^.connect := FALSE;
END;
END;
Output : BEGIN
IF (bpnp_(tva^.dptr)^.nt = hidden) THEN BEGIN
wnp_(wpt^.dptr)^.connect := TRUE;
END
ELSE BEGIN
wnp_(wpt^.dptr)^.connect := FALSE;
END;
END;
END; {case}
wpt := wpt^.right;
tva := tva^.right;
END;
tvd := tvd^.right;
tva := net.vs;
wpt := bpnp_(tvd^.dptr)^.fw;
END;
IF (debug) THEN {}
BEGIN
Writeln ('END SET_CONNECTIVITY');
Writeln (NET.OUT_F,'END SET_CONNECTIVITY');
END;
END;
PROCEDURE Display_output (VAR net : BP_net_);
{}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
BEGIN {}
IF debug THEN BEGIN
Writeln ('DISPLAY_OUTPUT');
Writeln (NET.OUT_F,'DISPLAY_OUTPUT');
END;
display_vector (net.vos,net.n_output,net);
IF (debug) THEN {}
BEGIN
Writeln ('END DISPLAY_OUTPUT');
Writeln (NET.OUT_F,'END DISPLAY_OUTPUT');
END;
END; {}
FUNCTION BP_error_measure (Output_vector_ptr : DVE_ptr_;
Training_vector_ptr : DVE_ptr_;
net : BP_net_): REAL;
BEGIN
END; {BP_error_measure}
{----------------------------------------------------------------------}
PROCEDURE BP_set_net_defaults (VAR net : BP_net_);
{}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
BEGIN {}
WITH net DO BEGIN {}
vs := NIL;
ve := NIL;
ws := NIL;
vi := NIL;
vos := NIL;
voe := NIL;
vts := NIL;
vte := NIL;
maxerr := 0.2;
errtol := 0.1;
learning_rate := 0.5;
alpha := 0.9; {factor for momentum term}
n_input := 1;
n_hidden := 1;
n_output := 1;
{ data_fname := 'BP.DAT';}
training_iterations := 1;
out_fname := 'BP.OUT';
wt_fname := '';
END; {}
END; {}
PROCEDURE BP_get_net_params_from_user (VAR net : BP_net_);
{}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
BEGIN {}
Write ('File to output run data to : ');
Readln (net.out_fname);
Assign (net.out_f,net.out_fname);
Rewrite (net.out_f);
{learning rate}
Write ('Learning rate? : ');
Readln (net.learning_rate);
Writeln (NET.OUT_F,'Learning rate : ',net.learning_rate:5:3);
Writeln ('Learning rate : ',net.learning_rate:5:3);
{momentum factor}
Write ('Momentum factor? : ');
Readln (net.alpha);
Writeln (NET.OUT_F,'Momentum factor : ',net.alpha:5:3);
Writeln ('Momentum factor : ',net.alpha:5:3);
{# of input nodes?} {BP_INPUT_NODES_NUM}
Write ('Number of input nodes? : ');
Readln (net.n_input);
Writeln (NET.OUT_F,'# of input nodes : ',net.n_input:3);
Writeln ('# of input nodes : ',net.n_input:3);
{# of hidden nodes in vector}
Write ('Number of hidden nodes? : ');
Readln (net.n_hidden);
Writeln (NET.OUT_F,'# of hidden nodes : ',net.n_hidden:3);
Writeln ('# of hidden nodes : ',net.n_hidden:3);
{# of output nodes}
Write ('Number of output nodes? : ');
Readln (net.n_output);
Writeln (NET.OUT_F,'# of output nodes : ',net.n_output:3);
Writeln ('# of output nodes : ',net.n_output:3);
{error tolerance}
Write ('Error tolerance? : ');
Readln (net.errtol);
Writeln (NET.OUT_F,'Error tolerance : ',net.errtol:5:3);
Writeln ('Error tolerance : ',net.errtol:5:3);
Writeln;
Write ('Name of data file : ');
Readln (net.data_fname);
Writeln (NET.OUT_F,'Data file : ',net.data_fname:15);
Writeln ('Data file : ',net.data_fname:15);
Write ('Number of training runs? : ');
Readln (net.training_iterations);
Writeln (NET.OUT_F,'# of iterations : ',
net.training_iterations:3);
Writeln ('# of iterations : ',net.training_iterations:3);
Writeln;
END; {}
PROCEDURE BP_set_net_params_from_file (VAR net : BP_net_;
VAR Fname : STRING);
{
Use the following format for data entries in this section:
!<option letter><space character><data item><CR>
where the !<option letter> combinations are as follows:
!L set learning_rate
!A set alpha factor for momentum term
!I set n_input
!H set n_hidden
!O set n_output
!T set training_iterations
!E set error tolerance
!D set data_fname
!R set out_fname
!W set wt_fname
!Z mark end of parameter data
}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
inch : CHAR;
done : BOOLEAN;
BEGIN {}
Fname := FSEARCH(Fname,GETENV('PATH'));
IF Length(Fname) = 0 THEN BEGIN
Writeln('**ERROR** File does not exist');
EXIT;
END;
Assign(net.data_f,Fname);
Reset(net.data_f);
done := FALSE;
REPEAT {get net params}
REPEAT {find command}
Read (net.data_f,inch);
UNTIL (inch = '!'); {}
Read (net.data_f,inch);
CASE UpCase(inch) OF
'L' : BEGIN {get learning rate}
Read (net.data_f, inch);
Read (net.data_f, net.learning_rate);
END; {}
'A' : BEGIN {get alpha}
Read (net.data_f, inch);
Read (net.data_f, net.alpha);
END; {}
'I' : BEGIN {get # inputs}
Read (net.data_f, inch);
Read (net.data_f, net.n_input);
END; {}
'E' : BEGIN {get error tolerance}
Read (net.data_f, inch);
Read (net.data_f, net.errtol);
END; {}
'H' : BEGIN {get # hidden units}
Read (net.data_f, inch);
Read (net.data_f, net.n_hidden);
END; {}
'O' : BEGIN {get # output units}
Read (net.data_f, inch);
Read (net.data_f, net.n_output);
END; {}
'T' : BEGIN {get # of training iterations}
Read (net.data_f, inch);
Read (net.data_f, net.training_iterations);
END; {}
'D' : BEGIN {get datafile name}
Read (net.data_f, inch);
Readln (net.data_f, net.data_fname);
END; {}
'R' : BEGIN {get outfile name}
Read (net.data_f, inch);
Readln (net.data_f, net.out_fname);
END; {}
'W' : BEGIN {get weight file name}
Read (net.data_f, inch);
Readln (net.data_f, net.wt_fname);
END; {}
'Z' : DONE := TRUE;
ELSE
BEGIN
DONE := TRUE;
END;
END;
UNTIL (done OR Eof (net.data_f));
{}
Close (net.data_f);
END; {BP_set_net_params_from_file}
{$V-}
PROCEDURE Setup_BP_net (VAR BPN : BP_net_;
VAR Fname : STRING);
{Get data values from a text file to set up basic BP constants, sizes,
and other necessary information, or query user if filename is not
valid.}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
s : STRING;
BEGIN {Setup_BP_net}
BP_set_net_defaults (BPN);
s := FSEARCH(Fname,GETENV('PATH'));
IF (s = '') THEN {}
BEGIN
BP_get_net_params_from_user (BPN);
END
ELSE {}
BEGIN
BP_set_net_params_from_file (BPN,s);
Assign(BPN.out_f,BPN.out_fname);
Rewrite(BPN.out_f);
END;
s := FSEARCH(BPN.data_fname,GETENV('PATH'));
IF (s = '') THEN {}
BEGIN
Assign(BPN.data_f,BPN.data_fname);
Rewrite(BPN.data_f);
Writeln(BPN.data_f);
Close(BPN.data_f);
Reset(BPN.data_f);
END
ELSE {}
BEGIN
Assign(BPN.data_f,s);
Reset(BPN.data_f);
END;
Randomize;
Allocate_IO_vectors (BPN);
Allocate_node_vector (BPN);
Allocate_weight_matrix (BPN);
Link_weights_to_nodes (BPN);
set_connectivity (BPN);
{ display_weights (BPN);}
END; {Setup_BP_net}
{$V+}
PROCEDURE set_input_vector_from_file (VAR BPN : BP_net_);
{Get data values from a text file to fill input vector.}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii : INTEGER;
inch : CHAR;
vp : DVE_ptr_;
nptr : DVE_ptr_;
BEGIN {}
IF debug THEN BEGIN
Writeln ('SET_INPUT_FROM_FILE');
Writeln (BPN.OUT_F,'SET_INPUT_FROM_FILE');
END;
IF Eof(BPN.data_f) THEN BEGIN
Close(BPN.data_f);
Reset(BPN.data_f);
END;
{find beginning of input line}
REPEAT {}
Read (BPN.data_f,inch);
IF (inch = '!') THEN {skip over net param commands}
BEGIN
Read (BPN.data_f,inch);
Read (BPN.data_f,inch);
END;
UNTIL (UpCase(inch) = 'I') OR (Eof(BPN.data_f));
{}
vp := BPN.vi;
IF NOT Eof(BPN.data_f) AND (vnp_(vp^.dptr) <> NIL) THEN BEGIN
FOR ii := 1 TO BPN.n_input DO BEGIN
{}
Read (BPN.data_f,vnp_(vp^.dptr)^.v);
vp := vp^.right;
END;
END;
IF (debug) THEN {}
BEGIN
Writeln ('END SET_INPUT_FROM_FILE');
Writeln (BPN.OUT_F,'END SET_INPUT_FROM_FILE');
END;
END; {}
PROCEDURE set_training_vector_from_file (VAR BPN : BP_net_);
{}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii : INTEGER;
inch : CHAR;
vp : DVE_ptr_;
nptr : DVE_ptr_;
BEGIN {}
IF debug THEN BEGIN
Writeln ('SET_TRAINING_V_FROM_FILE');
Writeln (BPN.OUT_F,'SET_TRAINING_V_FROM_FILE');
END;
IF Eof(BPN.data_f) THEN BEGIN
Close(BPN.data_f);
Reset(BPN.data_f);
END;
{find beginning of input line}
REPEAT {}
Read (BPN.data_f,inch);
IF (inch = '!') THEN {skip over net param commands}
BEGIN
Read (BPN.data_f,inch);
Read (BPN.data_f,inch);
END;
UNTIL (UpCase(inch) = 'T') OR (Eof(BPN.data_f));
{}
vp := BPN.vts;
IF NOT Eof (BPN.data_f) THEN
FOR ii := 1 TO BPN.n_output DO BEGIN
{}
Read (BPN.data_f,vnp_(vp^.dptr)^.v);
vp := vp^.right;
END;
IF (debug) THEN {}
BEGIN
Writeln ('END SET_TRAINING_V_FROM_FILE');
Writeln (BPN.OUT_F,'END SET_TRAINING_V_FROM_FILE');
END;
END; {}
PROCEDURE Back_propagate (VAR net : BP_net_);
{}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii, jj, n : INTEGER;
rr, ss : REAL;
tr, ts, tt, tu, tv : REAL;
npa, npd : DVE_ptr_; {node ptr across, down}
cw : DVE_ptr_; {current weight}
out, trn : DVE_ptr_;
inch : CHAR;
BEGIN {}
IF debug THEN BEGIN
Writeln ('BACK_PROPAGATE');
Writeln (NET.OUT_F,'BACK_PROPAGATE');
END;
n := net.n_input + net.n_hidden + net.n_output;
{calculate deltas for the nodes}
npa := net.ve; {node ptr across}
npd := net.vs; {node ptr down}
cw := bpnp_(net.ve^.dptr)^.bw;
{current weight ptr}
trn := net.vte; {training vector ptr}
out := net.voe; {output vector ptr}
FOR ii := 1 TO N DO BEGIN {}
cw := bpnp_(npa^.dptr)^.bw;
CASE bpnp_(npa^.dptr)^.nt OF
{node pointer across type}
Input, hidden : BEGIN {need to assign delta}
{set rr to current node output}
rr := sigmoid (bpnp_(npa^.dptr)^.range, 1,
bpnp_(npa^.dptr)^.base, (bpnp_(npa^.dptr)^.ni
+ bpnp_(npa^.dptr)^.theta));
{find error term from forward connections}
ss := 0;
npd := net.vs;
cw := bpnp_(npa^.dptr)^.bw;
FOR jj := 1 TO N DO BEGIN
{}
IF (wnp_(cw^.dptr)^.connect) THEN BEGIN
ss := ss + (bpnp_(npd^.dptr)^.delta
* wnp_(cw^.dptr)^.w);
END;
IF (jj < n) THEN BEGIN
npd := npd^.right;
cw := cw^.down;
END;
END; {}
IF DEBUG THEN
Write ('Delta node ',bpnp_(npa^.dptr)^.loc,' = ',
rr:6,' * (1 - ',rr:6,') * ',ss:6);
bpnp_(npa^.dptr)^.delta := rr * (1 - rr) * ss;
END;
Output : BEGIN {}
rr := sigmoid (bpnp_(npa^.dptr)^.range,1,
bpnp_(npa^.dptr)^.base,
(bpnp_(npa^.dptr)^.ni + bpnp_(npa^.dptr)^.theta));
IF DEBUG THEN
Write ('Delta node ',bpnp_(npa^.dptr)^.loc,' = (',
vnp_(trn^.dptr)^.v:6,' - ',vnp_(out^.dptr)^.v:6,
') * ', rr:6,' * (1 - ',rr:6,') = ');
IF (trn <> NIL) AND (out <> NIL) THEN BEGIN
bpnp_(npa^.dptr)^.delta := (vnp_(trn^.dptr)^.v
- vnp_(out^.dptr)^.v) * rr * (1 - rr);
rr := ABS (vnp_(trn^.dptr)^.v - vnp_(out^.dptr)^.v);
IF (net.maxerr < rr) THEN BEGIN
net.maxerr := rr;
END;
END
ELSE BEGIN
Writeln ('NIL pointer to train or output');
Halt;
END;
IF DEBUG THEN Writeln (bpnp_(NPA^.dptr)^.DELTA:6);
trn := trn^.left;
out := out^.left;
END; {CASE output term}
END; {CASE}
npa := npa^.left;
cw := bpnp_(npa^.dptr)^.bw;
END; {FOR ii}
{now calculate weight changes for weights and update}
npa := net.ve; {node ptr across}
npd := net.vs; {node ptr down}
cw := bpnp_(npa^.dptr)^.bw; {current weight ptr}
trn := net.vte; {training vector ptr}
out := net.voe; {output vector ptr}
FOR ii := 1 TO N DO BEGIN {}
npd := net.vs;
cw := bpnp_(npa^.dptr)^.bw;
FOR jj := 1 TO N DO BEGIN{}
IF (wnp_(cw^.dptr)^.connect) THEN
{}
BEGIN
rr := sigmoid(bpnp_(npa^.dptr)^.range,1,
bpnp_(npa^.dptr)^.base,
(bpnp_(npa^.dptr)^.ni + bpnp_(npa^.dptr)^.theta));
wnp_(cw^.dptr)^.dw := wnp_(cw^.dptr)^.dw
+ (net.learning_rate *
(bpnp_(npd^.dptr)^.delta * rr));
{error * activation}
END;
npd := npd^.right;
cw := cw^.down;
END; {}
IF DEBUG THEN
Writeln (bpnp_(npa^.dptr)^.delta:7,' ',bpnp_(npa^.dptr)
^.theta:7);
{From Simpson, II, p 73}
bpnp_(npa^.dptr)^.dtheta := bpnp_(npa^.dptr)^.dtheta + net.
learning_rate * bpnp_(npa^.dptr)^.delta;
{bpnp_(npa^.dptr)^.theta :=
bpnp_(npa^.dptr)^.theta +
bpnp_(npa^.dptr)^.dtheta;}
npa := npa^.left;
cw := bpnp_(npa^.dptr)^.bw;
END; {}
IF (debug) THEN {}
BEGIN
Writeln ('END BACK_PROPAGATE');
Writeln (NET.OUT_F,'END BACK_PROPAGATE');
END;
END; {}
PROCEDURE BP_Feed_forward (VAR BPN : BP_net_);
{Present values to network and propagate values forward, set the output
vector.}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii, jj, n : INTEGER;
rr, ss : REAL;
dp1, dp2, dp3 : DVE_ptr_;
npa, npd : DVE_ptr_;
np1 : BP_node_ptr_; {node ptr across, down}
cw : DVE_ptr_; {current weight}
vin, vout : DVE_ptr_;
BEGIN {}
IF debug THEN BEGIN
Writeln ('FEED_FORWARD');
Writeln (BPN.OUT_F,'FEED_FORWARD');
END;
{npd is the pointer to the node to change}
{npa points to the node that the current weight may modify the
output of}
n := BPN.n_input + BPN.n_hidden + BPN.n_output;
IF BPN.vs <> NIL THEN BEGIN
npa := BPN.vs;
npd := BPN.vs;
END
ELSE BEGIN
Writeln ('ERROR -- NIL pointer encountered #1');
Halt;
END;
IF (BP_node_ptr_(npd^.dptr)^.fw <> NIL) AND (BPN.VI <> NIL)
AND (BPN.vos <> NIL) THEN BEGIN
cw := BP_node_ptr_(npd^.dptr)^.fw;
vin := BPN.vi;
vout := BPN.vos;
END
ELSE BEGIN
Writeln ('ERROR -- NIL pointer encountered #2');
Halt;
END;
FOR ii := 1 TO N DO BEGIN {}
BP_node_ptr_(npd^.dptr)^.ni := 0;
IF (BP_node_ptr_(npd^.dptr)^.nt = Input) THEN
{}
BEGIN
BP_node_ptr_(npd^.dptr)^.ni := VNP_(vin^.dptr)^.v;
IF debug THEN Writeln ('I_node ',
BP_node_ptr_(npd^.dptr)^.loc,
' = ',VNP_(vin^.dptr)^.v:4);
vin := vin^.right;
END; {IF input}
npa := BPN.vs;
cw := BP_node_ptr_(npd^.dptr)^.fw;
FOR jj := 1 TO N DO BEGIN{}
IF (WNP_(cw^.dptr)^.connect) THEN
{}
BEGIN
IF (BP_node_ptr_(npa^.dptr)^.nt = Input) THEN
{}
BEGIN
IF DEBUG THEN
Write ('Node ',BP_node_ptr_(npd^.dptr)^.loc,
' = ', BP_node_ptr_(npd^.dptr)^.ni:4,' + ',
BP_node_ptr_(npa^.dptr)^.ni:4,' * ',
WNP_(cw^.dptr)^.w:4,' = ');
rr := BP_node_ptr_(npa^.dptr)^.ni
* WNP_(cw^.dptr)^.w;
BP_node_ptr_(npd^.dptr)^.ni :=
BP_node_ptr_(npd^.dptr)^.ni + rr;
IF DEBUG THEN Writeln (rr);
END
ELSE BEGIN
rr := (sigmoid(BP_node_ptr_(npa^.dptr)^.range,1,
BP_node_ptr_(npa^.dptr)^.base,
(BP_node_ptr_(npa^.dptr)^.ni
+ BP_node_ptr_(npa^.dptr)^.theta))
* WNP_(cw^.dptr)^.w);
IF DEBUG THEN
Writeln ('Node ',BP_node_ptr_(npd^.dptr)^.loc,
' = ', BP_node_ptr_(npd^.dptr)^.ni:4,' + ',rr:4);
BP_node_ptr_(npd^.dptr)^.ni :=
BP_node_ptr_(npd^.dptr)^.ni + rr;
END; {IF}
END; {IF cinnected}
IF (cw^.right <> NIL) AND (jj < n) THEN BEGIN
cw := cw^.right;
npa := npa^.right;
END
ELSE IF (cw^.right = NIL) AND (jj < n) THEN BEGIN
Writeln ('ERROR -- NIL pointer encountered #3 jj=',jj);
Halt;
END;
END; {FOR jj = 1 to N }
IF DEBUG THEN
Writeln ('Node net in : ',BP_node_ptr_(npd^.dptr)^.ni:6);
IF (BP_node_ptr_(npd^.dptr)^.nt = Output) THEN BEGIN
VNP_(vout^.dptr)^.v :=
sigmoid(BP_node_ptr_(npd^.dptr)^.range,1,
BP_node_ptr_(npd^.dptr)^.base,
(BP_node_ptr_(npd^.dptr)^.ni
+ BP_node_ptr_(npd^.dptr)^.theta));
vout := vout^.right;
END;
IF (npd^.right <> NIL)
AND (BP_node_ptr_(npd^.dptr)^.fw <> NIL)
AND (ii < N) THEN BEGIN
npd := npd^.right;
cw := BP_node_ptr_(npd^.dptr)^.fw;
END
ELSE IF ((npd^.right = NIL)
OR (BP_node_ptr_(npd^.dptr)^.fw = NIL))
AND (ii < n) THEN BEGIN
Writeln ('ERROR -- NIL pointer encountered #4');
IF (npd^.right = NIL) THEN Write ('NPD^.RIGHT is NIL ');
IF (BP_node_ptr_(npd^.dptr)^.fw = NIL) THEN Write (
'NPD^.FW is NIL ');
Writeln;
Halt;
END;
END; {}
IF (debug) THEN {}
BEGIN
Writeln ('END FEED_FORWARD');
Writeln (BPN.OUT_F,'END FEED_FORWARD');
END;
END; {}
PROCEDURE BP_train_presentation (VAR BPN : BP_net_);
{Present values to network, propagate forward, set output, compare
output to training, back-propagate, collect statistics but do not
change weights.}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
BEGIN {BP_train_presentation}
BP_feed_forward(BPN);
back_propagate(BPN);
END; {BP_train_presentation}
PROCEDURE BP_change (VAR BPN : BP_net_);
{Change weights using current statistics and reset statistics.}
{CONST}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii, jj : WORD;
node_total : WORD;
dp1, dp2, wp1, wp2 : DVE_ptr_;
bpnp1, bpnp2 :BP_node_ptr_;
wnp1, wnp2 : weight_node_ptr_;
BEGIN {BP_change}
node_total := BPN.n_input + BPN.n_hidden + BPN.n_output;
{Change thetas} {set pointer to first node}
dp1 := BPN.vs;
FOR ii := 1 TO node_total DO BEGIN
{set pointer to node}
bpnp1 := dp1^.dptr;
IF (bpnp1 <> NIL) THEN BEGIN
{set new theta value}
bpnp1^.ldtheta := bpnp1^.dtheta + BPN.alpha
* bpnp1^.ldtheta;
bpnp1^.theta := bpnp1^.theta + bpnp1^.ldtheta;
END
ELSE BEGIN
IF bpnp1 = NIL THEN Writeln (
'**Error** Nil ptr encountered: BP_unit.BP_change');
END;
IF bpnp1 <> NIL THEN BEGIN
{ bpnp1^.ldtheta := bpnp1^.dtheta;}
bpnp1^.dtheta := 0;
END; {set pointer to next node}
dp1 := dp1^.right;
END; {for ii}
{For each weight, do change, reset stats}
dp1 := BPN.ws;
FOR ii := 1 TO node_total DO BEGIN
dp2 := dp1;
FOR jj := 1 TO node_total DO BEGIN
IF (dp2 <> NIL) THEN BEGIN
wp1 := dp2^.dptr;
wnp_(wp1)^.ldw := wnp_(wp1)^.dw
+ BPN.alpha * wnp_(wp1)^.ldw;
wnp_(wp1)^.w := wnp_(wp1)^.w + wnp_(wp1)^.ldw;
wnp_(wp1)^.dw := 0;
dp2 := dp2^.right;
END;
END; {for jj}
dp1 := dp1^.down;
END; {for ii}
END; {BP_change}
PROCEDURE BP_train_and_change (VAR BPN : BP_net_);
{Present values to network, propagate forward, set output, compare output
to training, back-propagate, collect statistics, change weights, and
reset statistic variables.}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
BEGIN {BP_train_and_change}
BP_train_presentation(BPN);
BP_change(BPN);
END; {BP_train_and_change}
PROCEDURE BP_dump_net (VAR BPN : BP_net_);
{Dump net parameters, node activities, and weights for inspection.}
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
BEGIN {}
END; {}
PROCEDURE BP_driver (VAR net : BP_net_);
TYPE
bpnp_ = BP_node_ptr_;
wnp_ = weight_node_ptr_;
vnp_ = vector_node_ptr_;
VAR
ii : INTEGER;
nptr : DVE_ptr_;
BEGIN {}
{first, check for parameter}
IF (ParamCount > 0) THEN {}
BEGIN
net.data_fname := ParamStr(1);
Writeln ;
Writeln ('BACK PROPAGATION SIMULATION');
Writeln ;
DEBUG := FALSE;
{open data file}
Assign (net.data_f,net.data_fname);
Reset (net.data_f);
BP_set_net_params_from_file (net,net.data_fname);
{close data file}
Close (net.data_f);
END
ELSE {}
BEGIN
Writeln ;
Writeln ('BACK PROPAGATION SIMULATION');
Writeln ;
BP_get_net_params_from_user (net);
Write ('DEBUG ON OR OFF? (1 or 0) : ');
Readln (ii);
CASE ii OF
0 : debug := FALSE;
1 : debug := TRUE;
ELSE
debug := FALSE;
END;
END;
Assign (net.out_f,net.out_fname);
Rewrite (net.out_f);
Writeln (net.out_f,'DEBUG : ',debug);
Writeln ('DEBUG : ',debug);
{allocate input node vector}
{BP_INPUT_NODES_VECTOR}
{allocate hidden node vector}
{allocate output node vector}
{get scale for output node}
{allocate weight matrix}
{seed with random values}
{# to times to repeat data}
Randomize;
Allocate_IO_vectors (net);
Allocate_node_vector (net);
Allocate_weight_matrix (net);
Link_weights_to_nodes (net);
set_connectivity (net);
display_weights (net);
net.maxerr := net.errtol + 1.0;
ii := 1;
WHILE (net.maxerr > net.errtol)
AND (ii <= net.training_iterations) DO BEGIN
IF ((ii MOD 50) = 1) THEN BEGIN
Writeln (net.out_f,'At iteration ',ii);
Writeln ('At iteration ',ii);
END;
Assign (net.data_f,net.data_fname);
Reset (net.data_f);
net.maxerr := 0.0;
WHILE (NOT Eof (net.data_f)) DO BEGIN
{}
IF debug THEN Writeln ('In data loop ');
set_input_vector_from_file (net);
IF (NOT Eof(NET.DATA_F)) THEN BEGIN
IF ((ii MOD 50) = 1) THEN BEGIN
Writeln (NET.OUT_F);
Writeln ;
Write (net.out_f,'Input : ');
Write ('Input : ');
display_vector (net.vi,net.n_input,net);
END;
set_training_vector_from_file (net);
BP_feed_forward (net);
IF ((ii MOD 50) = 1) THEN BEGIN
Write (net.out_f,'Output : ');
Write ('Output : ');
display_vector (net.vos,net.n_output,net);
Write (net.out_f,'Expected : ');
Write ('Expected : ');
display_vector (net.vts,net.n_output,net);
END;
back_propagate (net);
END;
END; {}
Close (net.data_f);
ii := ii + 1;
END; {while ii and out of tolerance}
Writeln (net.out_f,'Iterations = ',ii);
Writeln ;
Writeln (net.out_f,'Weights after training : ');
Writeln ('Weights after training : ');
display_weights (net);
Writeln (NET.OUT_F);
Writeln ;
Writeln (NET.OUT_F,'Final values associated with nodes :');
Writeln ('Final values associated with nodes :');
nptr := net.vs;
FOR II := 1 TO (net.n_input + net.n_hidden + net.n_output) DO
BEGIN
dump_node (net,bpnp_(nptr^.dptr));
nptr := nptr^.right;
Writeln (net.out_f);
Writeln ;
END;
Flush (NET.OUT_F);
Close (NET.OUT_F);
END; {}
BEGIN {BP_unit}
END. {BP_unit}
{----------------------------------------------------------------------}