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__
|