view release on metacpan or search on metacpan
lib/AI/NeuralNet/Kohonen.pm view on Meta::CPAN
Reference to code to call at the end of every epoch
(such as a display routine).
=item train_end
Reference to code to call at the end of training.
=item targeting
If undefined, random targets are chosen; otherwise
they're iterated over. Just for experimental purposes.
=item smoothing
The amount of smoothing to apply by default when C<smooth>
is applied (see L</METHOD smooth>).
=item neighbour_factor
When working out the size of the neighbourhood of influence,
lib/AI/NeuralNet/Kohonen.pm view on Meta::CPAN
sub new {
my $class = shift;
my %args = @_;
my $self = bless \%args,$class;
$self->{missing_mask} = 'x' unless defined $self->{missing_mask};
$self->_process_table if defined $self->{table}; # Creates {input}
$self->load_input($self->{input_file}) if defined $self->{input_file}; # Creates {input}
if (not defined $self->{input}){
cluck "No {input} supplied!";
return undef;
}
$self->{map_dim_x} = 19 unless defined $self->{map_dim_x};
$self->{map_dim_y} = 19 unless defined $self->{map_dim_y};
# Legacy from...yesterday
if ($self->{map_dim}){
$self->{map_dim_x} = $self->{map_dim_y} = $self->{map_dim}
}
if (not defined $self->{map_dim_x} or $self->{map_dim_x}==0
or not defined $self->{map_dim_y} or $self->{map_dim_y}==0){
lib/AI/NeuralNet/Kohonen.pm view on Meta::CPAN
$self->{map_dim_a} = $self->{map_dim_x} + (($self->{map_dim_y}-$self->{map_dim_x})/2)
}
$self->{neighbour_factor} = 2.5 unless $self->{neighbour_factor};
$self->{epochs} = 99 unless defined $self->{epochs};
$self->{epochs} = 1 if $self->{epochs}<1;
$self->{time_constant} = $self->{epochs} / log($self->{map_dim_a}) unless $self->{time_constant}; # to base 10?
$self->{learning_rate} = 0.5 unless $self->{learning_rate};
$self->{l} = $self->{learning_rate};
if (not $self->{weight_dim}){
cluck "{weight_dim} not set";
return undef;
}
$self->randomise_map;
return $self;
}
=head1 METHOD randomise_map
lib/AI/NeuralNet/Kohonen.pm view on Meta::CPAN
missing_mask => $self->{missing_mask},
);
}
}
}
=head1 METHOD clear_map
As L<METHOD randomise_map> but sets all C<map> nodes to
either the value supplied as the only paramter, or C<undef>.
=cut
sub clear_map { my $self=shift;
confess "{weight_dim} not set" unless $self->{weight_dim};
confess "{map_dim_x} not set" unless $self->{map_dim_x};
confess "{map_dim_y} not set" unless $self->{map_dim_y};
my $val = shift || $self->{missing_mask};
my $w = [];
foreach (0..$self->{weight_dim}){
lib/AI/NeuralNet/Kohonen.pm view on Meta::CPAN
}
=head1 METHOD get_weight_at
Returns a reference to the weight array at the supplied I<x>,I<y>
co-ordinates.
Accepts: I<x>,I<y> co-ordinates, each a scalar.
Returns: reference to an array that is the weight of the node, or
C<undef> on failure.
=cut
sub get_weight_at { my ($self,$x,$y) = (shift,shift,shift);
return undef if $x<0 or $y<0 or $x>$self->{map_dim_x} or $y>$self->{map_dim_y};
return $self->{map}->[$x]->[$y]->{weight};
}
=head1 METHOD get_results
Finds and returns the results for all input vectors in the supplied
reference to an array of arrays,
placing the values in the C<results> field (array reference),
lib/AI/NeuralNet/Kohonen.pm view on Meta::CPAN
=head1 METHOD load_input
Loads a SOM_PAK-format file of input vectors.
This method is automatically accessed if the constructor is supplied
with an C<input_file> field.
Requires: a path to a file.
Returns C<undef> on failure.
See L</FILE FORMAT>.
=cut
sub load_input { my ($self,$path) = (shift,shift);
local *IN;
if (not open IN,$path){
warn "Could not open file <$path>: $!";
return undef;
}
@_ = <IN>;
close IN;
$self->_process_input_text(\@_);
return 1;
}
=head1 METHOD save_file
Saves the map file in I<SOM_PAK> format (see L<METHOD load_input>)
at the path specified in the first argument.
Return C<undef> on failure, a true value on success.
=cut
sub save_file { my ($self,$path) = (shift,shift);
local *OUT;
if (not open OUT,">$path"){
warn "Could not open file for writing <$path>: $!";
return undef;
}
#- Dimensionality of the vectors (integer, compulsory).
print OUT ($self->{weight_dim}+1)," "; # Perl indexing
#- Topology type, either hexa or rect (string, optional, case-sensitive).
if (not defined $self->{display}){
print OUT "rect ";
} else { # $self->{display} eq 'hex'
print OUT "hexa ";
}
#- Map dimension in x-direction (integer, optional).
lib/AI/NeuralNet/Kohonen.pm view on Meta::CPAN
chomp @_;
my @specs = split/\s+/,(shift @_);
#- Dimensionality of the vectors (integer, compulsory).
$self->{weight_dim} = shift @specs;
$self->{weight_dim}--; # Perl indexing
#- Topology type, either hexa or rect (string, optional, case-sensitive).
my $display = shift @specs;
if (not defined $display and exists $self->{display}){
# Intentionally blank
} elsif (not defined $display){
$self->{display} = undef;
} elsif ($display eq 'hexa'){
$self->{display} = 'hex'
} elsif ($display eq 'rect'){
$self->{display} = undef;
}
#- Map dimension in x-direction (integer, optional).
$_ = shift @specs;
$self->{map_dim_x} = $_ if defined $_;
#- Map dimension in y-direction (integer, optional).
$_ = shift @specs;
$self->{map_dim_y} = $_ if defined $_;
#- Neighborhood type, either bubble or gaussian (string, optional, case-sen- sitive).
# not implimented
lib/AI/NeuralNet/Kohonen.pm view on Meta::CPAN
$qerror /= scalar @$targets;
return $qerror;
}
=head1 PRIVATE METHOD _add_input_from_str
Adds to the C<input> field an input vector in SOM_PAK-format
whitespace-delimited ASCII.
Returns C<undef> on failure to add an item (perhaps because
the data passed was a comment, or the C<weight_dim> flag was
not set); a true value on success.
=cut
sub _add_input_from_str { my ($self) = (shift);
$_ = shift;
s/#.*$//g;
return undef if /^$/ or not defined $self->{weight_dim};
my @i = split /\s+/,$_;
return undef if $#i < $self->{weight_dim}; # catch bad lines
# 'x' in files signifies unknown: we prefer undef?
# @i[0..$self->{weight_dim}] = map{
# $_ eq 'x'? undef:$_
# } @i[0..$self->{weight_dim}];
my %args = (
dim => $self->{weight_dim},
values => [ @i[0..$self->{weight_dim}] ],
);
$args{class} = $i[$self->{weight_dim}+1] if $i[$self->{weight_dim}+1];
$args{enhance} = $i[$self->{weight_dim}+1] if $i[$self->{weight_dim}+2];
$args{fixed} = $i[$self->{weight_dim}+1] if $i[$self->{weight_dim}+3];
push @{$self->{input}}, new AI::NeuralNet::Kohonen::Input(%args);
return 1;
}
#
# Processes the 'table' paramter to the constructor
#
sub _process_table { my $self = shift;
$_ = $self->_process_input_text( $self->{table} );
undef $self->{table};
return $_;
}
__END__
1;
=head1 FILE FORMAT
This module has begun to attempt the I<SOM_PAK> format:
lib/AI/NeuralNet/Kohonen/Input.pm view on Meta::CPAN
=item dim
Scalar - the number of dimensions of this input vector.
Need not be supplied if C<values> is supplied.
=item values
Reference to an array containing the values for this
input vector. There should be one entry for each dimension,
with unknown values having the value C<undef>.
=item class
Optional class label string for this input vector.
=back
=cut
sub new {
my $class = shift;
my %args = @_;
my $self = bless \%args,$class;
if (not defined $self->{values}){
if (not defined $self->{dim}){
cluck "No {dim} or {weight}!";
return undef;
}
$self->{values} = [];
} elsif (not ref $self->{values}){
cluck "{values} not supplied!";
return undef;
} elsif (ref $self->{values} ne 'ARRAY') {
cluck "{values} should be an array reference, not $self->{values}!";
return undef;
} elsif (defined $self->{dim} and defined $self->{values}
and $self->{dim} ne $#{$self->{values}}){
cluck "{values} and {dim} do not match!";
return undef;
} else {
$self->{dim} = $#{$self->{values}};
}
return $self;
}
1;
lib/AI/NeuralNet/Kohonen/Node.pm view on Meta::CPAN
=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.
lib/AI/NeuralNet/Kohonen/Node.pm view on Meta::CPAN
\/ 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 += (
t/AI-NeuralNet-Kohonen.t view on Meta::CPAN
use strict;
use warnings;
use_ok ("AI::NeuralNet::Kohonen" => 0.14);
use_ok ("AI::NeuralNet::Kohonen::Node" => 0.12);
use_ok ("AI::NeuralNet::Kohonen::Input");
my ($dir) = $0 =~ /^(.*?)[^\\\/]+$/;
my $net = new AI::NeuralNet::Kohonen;
is($net,undef);
$net = new AI::NeuralNet::Kohonen(
weight_dim => 2,
input => [
[1,2,3]
],
);
isa_ok( $net->{input}, 'ARRAY');
is( $net->{input}->[0]->[0],1);
t/AI-NeuralNet-Kohonen.t view on Meta::CPAN
[1,2,3]
],
map_dim_x => 10,
map_dim_y => 20,
);
is($net->{map_dim_a},15);
# Node test
my $node = new AI::NeuralNet::Kohonen::Node;
is($node,undef) or BAIL_OUT();
$node = new AI::NeuralNet::Kohonen::Node(
weight => [0.1, 0.6, 0.5],
);
isa_ok( $node, 'AI::NeuralNet::Kohonen::Node');
is( $node->{dim}, 2);
my $input = new AI::NeuralNet::Kohonen::Input(
dim => 2,
values => [1,0,0],
);