AI-NeuralNet-FastSOM

 view release on metacpan or  search on metacpan

Makefile.PL  view on Meta::CPAN

#
# everything below is a work-around for some sort of bug in ExtUtils::ParseXS
# not picking up typemap files unless named "typemap" in perl5.6.2
#
# note however that the TYPEMAPS entry above is still needed for 5.6.2's still
# using the old xsubpp
#

package MY;

sub xs_c {
    my $t = shift->SUPER::xs_c(@_);
    $t =~ s/:/:\n	\$(MAKE) typemap/;
    $t;
}

sub test {
    my $t = shift->SUPER::test(@_);
    $t =~ s/(PERL_DL_NONLAZY=)/HARNESS_OPTIONS=j1 $1/g;
    $t;
}

sub postamble {
    my $out = <<'README';
readme:
	pod2text lib/AI/NeuralNet/FastSOM.pm README
	perl -i -pe's{\\*(\\S+)\\*}{\\1}g' README

README

    if ( $] < 5.008000 ) {
        $out .= <<'EOP';
typemap:

examples/eigenvector_initialization.pl  view on Meta::CPAN

#	print $E;
#	print $e;

	my @es = list $e;                                                # eigenvalues
#	warn "es : ".Dumper \@es;
	my @es_desc = sort { $b <=> $a } @es;                            # eigenvalues sorted desc
#	warn "desc: ".Dumper \@es_desc;
	my @es_idx  = map { _find_num ($_, \@es) } @es_desc;             # eigenvalue indices sorted by eigenvalue (desc)
#	warn "idx: ".Dumper \@es_idx;

sub _find_num {
    my $v = shift;
    my $l = shift;
    for my $i (0..$#$l) {
	return $i if $v == $l->[$i];
    }
    return undef;
}

	for (@es_idx) {                                                  # from the highest values downwards, take the index
	    push @training_vectors, [ list $E->dice($_) ] ;              # get the corresponding vector

examples/load_save.pl  view on Meta::CPAN

#	print $E;
#	print $e;

	my @es = list $e;                                                # eigenvalues
#	warn "es : ".Dumper \@es;
	my @es_desc = sort { $b <=> $a } @es;                            # eigenvalues sorted desc
#	warn "desc: ".Dumper \@es_desc;
	my @es_idx  = map { _find_num ($_, \@es) } @es_desc;             # eigenvalue indices sorted by eigenvalue (desc)
#	warn "idx: ".Dumper \@es_idx;

sub _find_num {
    my $v = shift;
    my $l = shift;
    for my $i (0..$#$l) {
	return $i if $v == $l->[$i];
    }
    return undef;
}

	for (@es_idx) {                                                  # from the highest values downwards, take the index
	    push @training_vectors, [ list $E->dice($_) ] ;              # get the corresponding vector

lib/AI/NeuralNet/FastSOM.pm  view on Meta::CPAN

package AI::NeuralNet::FastSOM;

use strict;
use warnings;
use XSLoader;

our $VERSION = '0.19';

sub new { die 'Dont use this class directly' }

sub label {
	my ($self, $x, $y, $l) = @_;
	return defined $l
		? $self->{labels}->[$x]->[$y] = $l
		: $self->{labels}->[$x]->[$y];
}

sub value {
	my ($self, $x, $y, $v) = @_;
	return defined $v
		? $self->{map}[$x][$y] = $v
		: $self->{map}[$x][$y];
}

sub mean_error {
    my $self = shift;
    my $error = 0;
    map { $error += $_ }                    # then add them all up
        map { ( $self->bmu($_) )[2] }       # then find the distance
           @_;                              # take all data vectors
    return ($error / scalar @_);            # return the mean value
}

XSLoader::load(__PACKAGE__);

lib/AI/NeuralNet/FastSOM/Hexa.pm  view on Meta::CPAN

package AI::NeuralNet::FastSOM::Hexa;

use strict;
use warnings;

use AI::NeuralNet::FastSOM;
our @ISA = qw/AI::NeuralNet::FastSOM/;

our $VERSION = '0.19';

sub radius   { shift->{_R} }
sub diameter { shift->{_X} }

sub as_data   { die 'not implemented' }
sub as_string { die 'not implemented' }

sub initialize {
    my $self = shift;
    my @data = @_;

    our $i = 0;
    my $get_from_stream = sub {
        $i = 0 if $i > $#data;
        return [ @{ $data[$i++] } ];  # cloning !
    } if @data;
    $get_from_stream ||= sub {
        return [ map { rand( 1 ) - 0.5 } 1..$self->{_Z} ];
    };

    for my $x (0 .. $self->{_X}-1) {
        for my $y (0 .. $self->{_X}-1) {
            $self->{map}->[$x]->[$y] = &$get_from_stream;
        }
    }
}

lib/AI/NeuralNet/FastSOM/Hexa.pm  view on Meta::CPAN

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2009-2016 by Rick Myers

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.10.0 or,
at your option, any later version of Perl 5 you may have available.

=cut

sub _get_coordinates {
    my $self = shift;
    my $D1 = $self->{_D}-1;
    my $t;
    return map { $t = $_ ; map { [ $t, $_ ] } (0 .. $D1) } (0 .. $D1)
}

sqrt ( ($x - $X) ** 2 + ($y - $Y) ** 2 );

lib/AI/NeuralNet/FastSOM/Rect.pm  view on Meta::CPAN

package AI::NeuralNet::FastSOM::Rect;

use strict;
use warnings;

use AI::NeuralNet::FastSOM;
our @ISA = qw/AI::NeuralNet::FastSOM/;

our $VERSION = '0.19';

sub _old_radius { shift->{_R} }

sub initialize {
    my $self = shift;
    my @data = @_;

    my $i = 0;

    my $get_from_stream = sub {
        $i = 0 if $i > $#data;
        return [ @{ $data[$i++] } ];  # cloning !
    } if @data;

    $get_from_stream ||= sub {
        return [ map { rand( 1 ) - 0.5 } 1..$self->{_Z} ];
    };

    for my $x (0 .. $self->{_X}-1) {
        for my $y (0 .. $self->{_Y}-1) {
            $self->{map}->[$x]->[$y] = &$get_from_stream;
        }
    }
}

sub as_string {
    my $self = shift;
    my $s = '';

    $s .= "    ";
    for my $y (0 .. $self->{_Y}-1){
        $s .= sprintf("   %02d ",$y);
    }
    $s .= "\n" . "-"x107 . "\n";

    my $dim = scalar @{ $self->{map}->[0]->[0] };

lib/AI/NeuralNet/FastSOM/Rect.pm  view on Meta::CPAN

            for my $y (0 .. $self->{_Y}-1){
                $s .= sprintf("% 2.2f ", $self->{map}->[$x]->[$y]->[$w]);
            }
            $s .= "\n";
        }
        $s .= "\n";
    }
    return $s;
}

sub as_data {
    my $self = shift;
    my $s = '';

    my $dim = scalar @{ $self->{map}->[0]->[0] };
    for my $x (0 .. $self->{_X}-1) {
        for my $y (0 .. $self->{_Y}-1){
            for my $w ( 0 .. $dim-1 ){
                $s .= sprintf("\t%f", $self->{map}->[$x]->[$y]->[$w]);
            }
            $s .= "\n";

t/orig/rect.t  view on Meta::CPAN

#    print Dumper $nn;
#    exit;

    my @vs = ([ 3, 2, 4 ], [ -1, -1, -1 ], [ 0, 4, -3]);
    $nn->train (400, @vs);

    foreach my $v (@vs) {
	ok (_find ($v, $nn->map), 'found learned vector '. join (",", @$v));
    }

sub _find {
    my $v = shift;
    my $m = shift;

    use AI::NeuralNet::FastSOM::Utils;
    foreach my $x ( 0 .. 4 ) {
	foreach my $y ( 0 .. 5 ) {
	    return 1 if AI::NeuralNet::FastSOM::Utils::vector_distance ($m->[$x]->[$y], $v) < 0.01;
	}
    }
    return 0;

t/orig/rect.t  view on Meta::CPAN

	foreach my $y (0 .. 6 -1 ) {
	    ok ( (!grep { $_ > 0.5 || $_ < -0.5 } @{ $nn->value ( $x, $y ) }) , "$x, $y: random vectors in [-0.5, 0.5]");
	}
    }
}

__END__

# randomized pick
    @vectors = ...;
my $get = sub {
    return @vectors [ int (rand (scalar @vectors) ) ];
    
}
$nn->train ($get);

# take exactly 500, round robin, in order
our $i = 0;
my $get = sub {
    return undef unless $i < 500;
return @vectors [ $i++ % scalar @vectors ];
}

t/orig/som.t  view on Meta::CPAN

	my @mes = $nn->train (20, @vs);
	is (scalar @mes, 3 * 20, 'errors while training, nr');
	ok ((!grep { $_ > 10 * $me } @mes), 'errors while training, none significantly bigger');
    }
}

__END__

# randomized pick
    @vectors = ...;
my $get = sub {
    return @vectors [ int (rand (scalar @vectors) ) ];
    
}
$nn->train ($get);

# take exactly 500, round robin, in order
our $i = 0;
my $get = sub {
    return undef unless $i < 500;
return @vectors [ $i++ % scalar @vectors ];
}

t/orig/torus.t  view on Meta::CPAN

#    print Dumper $nn;
#    exit;

    my @vs = ([ 3, 2, 4 ], [ -1, -1, -1 ], [ 0, 4, -3]);
    $nn->train (400, @vs);

    foreach my $v (@vs) {
	ok (_find ($v, $nn->map), 'found learned vector '. join (",", @$v));
    }

sub _find {
    my $v = shift;
    my $m = shift;

    use AI::NeuralNet::FastSOM::Utils;
    foreach my $x ( 0 .. 4 ) {
	foreach my $y ( 0 .. 5 ) {
	    return 1 if AI::NeuralNet::FastSOM::Utils::vector_distance ($m->[$x]->[$y], $v) < 0.01;
	}
    }
    return 0;

t/orig/torus.t  view on Meta::CPAN

    ok ($nn->as_string, 'pretty print');
    ok ($nn->as_data, 'raw format');

#    print $nn->as_string;
}

__END__

# randomized pick
    @vectors = ...;
my $get = sub {
    return @vectors [ int (rand (scalar @vectors) ) ];
    
}
$nn->train ($get);

# take exactly 500, round robin, in order
our $i = 0;
my $get = sub {
    return undef unless $i < 500;
return @vectors [ $i++ % scalar @vectors ];
}

t/rect.t  view on Meta::CPAN

        input_dim  => 3
    );
    ok ($nn->isa ('AI::NeuralNet::FastSOM::Rect'), 'class');
    is ($nn->{_X}, 5, 'X');
    is ($nn->{_Y}, 6, 'Y');
    is ($nn->{_Z}, 3, 'Z');
    is ($nn->radius, 2.5, 'radius');
    is ($nn->output_dim, "5x6", 'output dim');
}

sub _find {
    my $v = shift;
    my $m = shift;

    for my $x ( 0 .. 4 ) {
        for my $y ( 0 .. 5 ) {
            my $rv = AI::NeuralNet::FastSOM::Utils::vector_distance($m->[$x]->[$y], $v);
            return 1 if $rv < 0.01;
        }
    }
    return 0;

t/torus.t  view on Meta::CPAN

                [ 3, 1, '1' ],
                [ 3, 2, '0' ],
                [ 3, 3, '1' ],
                [ 4, 2, '1' ]
            ]
        ),
        'neighbors 4+1'
    );
}

sub _find {
    my $v = shift;
    my $m = shift;

    for my $x ( 0 .. 4 ) {
        for my $y ( 0 .. 5 ) {
            return 1
                if AI::NeuralNet::FastSOM::Utils::vector_distance( $m->[$x]->[$y], $v ) < 0.01;
        }
    }
    return 0;



( run in 1.516 second using v1.01-cache-2.11-cpan-a5abf4f5562 )