File Coverage

blib/lib/AI/NeuralNet/Kohonen/Node.pm
Criterion Covered Total %
statement 41 47 87.2
branch 11 16 68.7
condition 4 12 33.3
subroutine 8 8 100.0
pod 0 3 0.0
total 64 86 74.4


line stmt bran cond sub pod time code
1             package AI::NeuralNet::Kohonen::Node;
2            
3 1     1   6 use vars qw/$VERSION $TRACE/;
  1         8  
  1         77  
4             $VERSION = 0.12; # 05 May 2006; no warnings 'numeric' inserted
5             $TRACE = 1;
6            
7             =head1 NAME
8            
9             AI::NeuralNet::Kohonen::Node - a node for AI::NeuralNet::Kohonen
10            
11             =head1 DESCRIPTION
12            
13             Implimentation of a node in a SOM - see
14             L.
15            
16             =cut
17            
18 1     1   6 use strict;
  1         2  
  1         27  
19 1     1   4 use warnings;
  1         2  
  1         26  
20 1     1   5 use Carp qw/cluck carp confess croak/;
  1         1  
  1         445  
21            
22             =head1 CONSTRUCTOR (new)
23            
24             Returns a new C object. If no wieghts
25             are supplied, the node's weights are randomized
26             with real nubmers.
27            
28             =over 4
29            
30             =item dim
31            
32             The number of dimensions of this node's weights.
33             Do not supply if you are supplying C.
34            
35             =item weight
36            
37             Optional: a reference to an array containing the
38             weight for this node. Supplying this allows the
39             constructor to work out C, above.
40            
41             =item values
42            
43             The values of the vector. Use C for unknown values.
44            
45             =item missing_mask
46            
47             Used to donate missing input in the node. Default is C.
48            
49             =back
50            
51             =cut
52            
53             sub new {
54 798     798 0 3061 my $class = shift;
55 798         3070 my %args = @_;
56 798         2162 my $self = bless \%args,$class;
57 798 100       2425 $self->{missing_mask} = 'x' unless defined $self->{missing_mask};
58 798 100 33     1588 if (not defined $self->{weight}){
    50          
59 797 100       2064 if (not defined $self->{dim}){
60 1         332 cluck "No {dim} or {weight}!";
61 1         7 return undef;
62             }
63 796         1658 $self->{weight} = [];
64 796         2661 for my $w (0..$self->{dim}){
65 2388         5884 $self->{weight}->[$w] = rand;
66             }
67             } elsif (not ref $self->{weight} or ref $self->{weight} ne 'ARRAY') {
68 0         0 cluck "{weight} should be an array reference!";
69 0         0 return undef;
70             } else {
71 1         2 $self->{dim} = $#{$self->{weight}};
  1         6  
72             }
73 797         3942 return $self;
74             }
75            
76            
77             =head1 METHOD distance_from
78            
79             Find the distance of this node from the target.
80            
81             Accepts: the target vector as an array reference.
82            
83             Returns: the distance.
84            
85             __________________
86             / i=n 2
87             Distance = / E ( V - W )
88             \/ i=0 i i
89            
90             Where C is the current input vector, and
91             C is this node's weight vector.
92            
93             =cut
94            
95 2311     2311 0 3448 sub distance_from { my ($self,$target) = (shift,shift);
96 2311 50 33     15196 if (not defined $target or not ref $target or ref $target ne 'AI::NeuralNet::Kohonen::Input'){
      33        
97 0         0 cluck "distance_from requires a target ::Input object!";
98 0         0 return undef;
99             }
100 2311 50       2474 if ($#{$target->{values}} != $self->{dim}){
  2311         6814  
101 0         0 croak "distance_from requires the target's {value} field dim match its own {dim}!\n"
102 0         0 ."(".($#{$target->{values}})." v {".$self->{dim}."} ) ";
103             }
104 2311         2902 my $distance = 0;
105 2311         5465 for (my $i=0; $i<=$self->{dim}; ++$i){
106 1     1   6 no warnings 'numeric';
  1         2  
  1         209  
107 6933 50       17224 next if $target->{values}->[$i] eq $self->{missing_mask};
108 6933         24485 $distance += (
109             ( $target->{values}->[$i] - $self->{weight}->[$i] )
110             * ( $target->{values}->[$i] - $self->{weight}->[$i] )
111             );
112             }
113 2311         6586 return sqrt($distance);
114             }
115            
116            
117             =head1 METHOD distance_effect
118            
119             Calculates the effect on learning of distance from a given point
120             (intended to be the BMU).
121            
122             Accepts:
123             the distance of this node from the given point;
124             the radius of the neighbourhood of affect around the given point.
125            
126             Returns:
127            
128             ( 2 )
129             ( distance )
130             THETA(t) = exp ( - ----------- )
131             ( 2 )
132             ( 2 sigma (t) )
133            
134             Where C is the distance of the node from the BMU,
135             and C is the width of the neighbourhood as calculated
136             elsewhere (see L). THETA also
137             decays over time.
138            
139             The time C is always that of the calling object, and is not referenced here.
140            
141             =cut
142            
143 54     54 0 115 sub distance_effect { my ($self,$distance,$sigma) = (shift,shift,shift);
144 54 50 33     227 confess "Wrong args" unless defined $distance and defined $sigma;
145 54         363 return exp (-($distance*$distance) / 2 * ($sigma*$sigma))
146             }
147            
148             1;
149            
150             __END__