package AI::NeuralNet::Kohonen::Node;
use vars qw/$VERSION $TRACE/;
$VERSION = 0.12; # 05 May 2006; no warnings 'numeric' inserted
$TRACE = 1;
=head1 NAME
AI::NeuralNet::Kohonen::Node - a node for AI::NeuralNet::Kohonen
=head1 DESCRIPTION
Implimentation of a node in a SOM - see
L<AI::NeuralNet::Kohonen>.
=cut
use strict;
use warnings;
use Carp qw/cluck carp confess croak/;
=head1 CONSTRUCTOR (new)
Returns a new C<Node> object. If no wieghts
are supplied, the node's weights are randomized
with real nubmers.
=over 4
=item dim
The number of dimensions of this node's weights.
Do not supply if you are supplying C<weight>.
=item weight
Optional: a reference to an array containing the
weight for this node. Supplying this allows the
constructor to work out C<dim>, above.
=item values
The values of the vector. Use C<x> for unknown values.
=item missing_mask
Used to donate missing input in the node. Default is C<x>.
=back
=cut
sub new {
my $class = shift;
my %args = @_;
my $self = bless \%args,$class;
$self->{missing_mask} = 'x' unless defined $self->{missing_mask};
if (not defined $self->{weight}){
if (not defined $self->{dim}){
cluck "No {dim} or {weight}!";
return undef;
}
$self->{weight} = [];
for my $w (0..$self->{dim}){
$self->{weight}->[$w] = rand;
}
} elsif (not ref $self->{weight} or ref $self->{weight} ne 'ARRAY') {
cluck "{weight} should be an array reference!";
return undef;
} else {
$self->{dim} = $#{$self->{weight}};
}
return $self;
}
=head1 METHOD distance_from
Find the distance of this node from the target.
Accepts: the target vector as an array reference.
Returns: the distance.
__________________
/ i=n 2
Distance = / E ( V - W )
\/ i=0 i i
Where C<V> is the current input vector, and
C<W> is this node's weight vector.
=cut
sub distance_from { my ($self,$target) = (shift,shift);
if (not defined $target or not ref $target or ref $target ne 'AI::NeuralNet::Kohonen::Input'){
cluck "distance_from requires a target ::Input object!";
return undef;
}
if ($#{$target->{values}} != $self->{dim}){
croak "distance_from requires the target's {value} field dim match its own {dim}!\n"
."(".($#{$target->{values}})." v {".$self->{dim}."} ) ";
}
my $distance = 0;
for (my $i=0; $i<=$self->{dim}; ++$i){
no warnings 'numeric';
next if $target->{values}->[$i] eq $self->{missing_mask};
$distance += (
( $target->{values}->[$i] - $self->{weight}->[$i] )
* ( $target->{values}->[$i] - $self->{weight}->[$i] )
);
}
return sqrt($distance);
}
=head1 METHOD distance_effect
Calculates the effect on learning of distance from a given point
(intended to be the BMU).
Accepts:
the distance of this node from the given point;
the radius of the neighbourhood of affect around the given point.
Returns:
( 2 )
( distance )
THETA(t) = exp ( - ----------- )
( 2 )
( 2 sigma (t) )
Where C<distance> is the distance of the node from the BMU,
and C<sigma> is the width of the neighbourhood as calculated
elsewhere (see L<AI::NeuralNet::Kohonen/FINDING THE NEIGHBOURS OF THE BMU>). THETA also
decays over time.
The time C<t> is always that of the calling object, and is not referenced here.
=cut
sub distance_effect { my ($self,$distance,$sigma) = (shift,shift,shift);
confess "Wrong args" unless defined $distance and defined $sigma;
return exp (-($distance*$distance) / 2 * ($sigma*$sigma))
}
1;
__END__
=head1 SEE ALSO
The L<AI::NeuralNet::Kohonen>.
=head1 AUTHOR AND COYRIGHT
This implimentation Copyright (C) Lee Goddard, 2003.
All Rights Reserved.
Available under the same terms as Perl itself.