File Coverage

blib/lib/AI/NNFlex/Mathlib.pm
Criterion Covered Total %
statement 26 78 33.3
branch 6 22 27.2
condition 0 3 0.0
subroutine 4 11 36.3
pod 4 10 40.0
total 40 124 32.2


line stmt bran cond sub pod time code
1             #######################################################
2             # AI::NNFlex::Mathlib
3             #######################################################
4             # Various custom mathematical functions for AI::NNFlex
5             #######################################################
6             #
7             # Version history
8             # ===============
9             #
10             # 1.0 CColbourn 20050315 Compiled into a
11             # single module
12             #
13             # 1.1 CColbourn 20050321 added in sigmoid_slope
14             #
15             # 1.2 CColbourn 20050330 Added in hopfield_threshold
16             #
17             # 1,3 CColbourn 20050407 Changed sigmoid function to
18             # a standard sigmoid. sigmoid2
19             # now contains old sigmoid,
20             # which is more used in BPTT
21             # and I think needs cross
22             # entropy calc to work.
23             #
24             #######################################################
25             #Copyright (c) 2004-2005 Charles Colbourn. All rights reserved. This program is free software; you can redistribute it and/or modify
26              
27             package AI::NNFlex::Mathlib;
28 5     5   33 use strict;
  5         8  
  5         4725  
29              
30             #######################################################
31             # tanh activation function
32             #######################################################
33             sub tanh
34             {
35              
36 16     16 1 20 my $network = shift;
37 16         19 my $value = shift;
38              
39 16         20 my @debug = @{$network->{'debug'}};
  16         39  
40              
41 16         42 my $a = exp($value);
42 16         23 my $b = exp(-$value);
43 16 50       45 if ($value > 20){ $value=1;}
  0 50       0  
44 0         0 elsif ($value < -20){ $value= -1;}
45             else
46             {
47 16         20 my $a = exp($value);
48 16         19 my $b = exp(-$value);
49 16         29 $value = ($a-$b)/($a+$b);
50             }
51 16 50       33 if (scalar @debug > 0)
  0         0  
52             {$network->dbug("Tanh activation returning $value",5)};
53 16         63 return $value;
54             }
55              
56             sub tanh_slope
57             {
58 0     0 0 0 my $network = shift;
59 0         0 my $value = shift;
60 0         0 my @debug = @{$network->{'debug'}};
  0         0  
61              
62              
63 0         0 my $return = 1-($value*$value);
64 0 0       0 if (scalar @debug > 0)
  0         0  
65             {$network->dbug("Tanh_slope returning $value",5);}
66              
67 0         0 return $return;
68             }
69              
70             #################################################################
71             # Linear activation function
72             #################################################################
73             sub linear
74             {
75              
76 0     0 1 0 my $network = shift;
77 0         0 my $value = shift;
78              
79 0         0 my @debug = @{$network->{'debug'}};
  0         0  
80 0 0       0 if (scalar @debug >0)
  0         0  
81             {$network->dbug("Linear activation returning $value",5)};
82 0         0 return $value;
83             }
84              
85             sub linear_slope
86             {
87 0     0 0 0 my $network = shift;
88 0         0 my $value = shift;
89 0         0 my @debug = @{$network->{'debug'}};
  0         0  
90 0 0       0 if (scalar @debug >0)
  0         0  
91             {$network->dbug("Linear slope returning $value",5)};
92 0         0 return $value;
93             }
94              
95              
96             ############################################################
97             # P&B sigmoid activation (needs slope)
98             ############################################################
99              
100             sub sigmoid2
101             {
102 0     0 0 0 my $network = shift;
103 0         0 my $value = shift;
104 0         0 $value = (1+exp(-$value))**-1;
105 0         0 $network->dbug("Sigmoid activation returning $value",5);
106 0         0 return $value;
107             }
108              
109             sub sigmoid2_slope
110             {
111 0     0 0 0 my $network = shift;
112 0         0 my $value = shift;
113 0         0 my @debug = @{$network->{'debug'}};
  0         0  
114              
115              
116 0         0 my $return = exp(-$value) * ((1 + exp(-$value)) ** -2);
117 0 0       0 if (scalar @debug > 0)
  0         0  
118             {$network->dbug("sigmoid_slope returning $value",5);}
119              
120 0         0 return $return;
121             }
122              
123             ############################################################
124             # standard sigmoid activation
125             ############################################################
126              
127             sub sigmoid
128             {
129 16     16 0 14 my $network = shift;
130 16         17 my $value = shift;
131 16         43 $value = 1/(1+exp(1)**-$value);
132 16         82 $network->dbug("Sigmoid activation returning $value",5);
133 16         34 return $value;
134             }
135              
136             sub sigmoid_slope
137             {
138 0     0 0 0 my $network = shift;
139 0         0 my $value = shift;
140 0         0 my @debug = @{$network->{'debug'}};
  0         0  
141              
142              
143 0         0 my $return = $value * (1-$value);
144 0 0       0 if (scalar @debug > 0)
  0         0  
145             {$network->dbug("sigmoid_slope returning $value",5);}
146              
147 0         0 return $return;
148             }
149              
150             ############################################################
151             # hopfield_threshold
152             # standard hopfield threshold activation - doesn't need a
153             # slope (because hopfield networks don't use them!)
154             ############################################################
155             sub hopfield_threshold
156             {
157 4     4 1 7 my $network = shift;
158 4         5 my $value = shift;
159              
160 4 100       12 if ($value <0){return -1}
  2         10  
161 2 50       6 if ($value >0){return 1}
  2         10  
162 0           return $value;
163             }
164              
165             ############################################################
166             # atanh error function
167             ############################################################
168             sub atanh
169             {
170 0     0 1   my $network = shift;
171 0           my $value = shift;
172 0 0 0       if ($value >-0.5 && $value <0.5)
173             {
174 0           $value = log((1+$value)/(1-$value))/2;
175             }
176 0           return $value;
177             }
178              
179             1;
180              
181             =pod
182              
183             =head1 NAME
184              
185             AI::NNFlex::Mathlib - miscellaneous mathematical functions for the AI::NNFlex NN package
186              
187             =head1 DESCRIPTION
188              
189             The AI::NNFlex::Mathlib package contains activation and error functions. At present there are the following:
190              
191             Activation functions
192              
193             =over
194              
195             =item *
196             tanh
197              
198             =item *
199             linear
200              
201             =item *
202             hopfield_threshold
203              
204             =back
205              
206             Error functions
207              
208             =over
209              
210             =item *
211             atanh
212              
213             =back
214              
215             If you want to implement your own activation/error functions, you can add them to this module. All activation functions to be used by certain types of net (like Backprop) require an additional function _slope, which returns the 1st order derivative of the function.
216              
217             This rule doesn't apply to all network types. Hopfield for example requires no slope calculation.
218              
219             =head1 CHANGES
220              
221             v1.2 includes hopfield_threshold
222              
223             =head1 COPYRIGHT
224              
225             Copyright (c) 2004-2005 Charles Colbourn. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
226              
227             =head1 CONTACT
228              
229             charlesc@nnflex.g0n.net
230              
231              
232              
233             =cut