view release on metacpan or search on metacpan
lib/AI/NNEasy.pm view on Meta::CPAN
use Class::HPLOO::Base ;
use AI::NNEasy::NN ;
use Storable qw(freeze thaw) ;
use Data::Dumper ;
sub NNEasy {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $file = shift(@_) ;
my @out_types = ref($_[0]) eq 'ARRAY' ? @{ shift(@_) } : ( ref($_[0]) eq 'HASH' ? %{ shift(@_) } : shift(@_) ) ;
my $error_ok = shift(@_) ;
my $in = shift(@_) ;
my $out = shift(@_) ;
my @layers = ref($_[0]) eq 'ARRAY' ? @{ shift(@_) } : ( ref($_[0]) eq 'HASH' ? %{ shift(@_) } : shift(@_) ) ;
my $conf = shift(@_) ;
$file ||= 'nneasy.nne' ;
lib/AI/NNEasy.pm view on Meta::CPAN
$error_ok = $min_dif / 2 ;
$error_ok -= $error_ok*0.1 ;
}
$this->{ERROR_OK} = $error_ok ;
return $this ;
}
sub _layer_conf {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $def = shift(@_) ;
my $conf = shift(@_) ;
$def ||= {} ;
$conf = { nodes=>$conf } if !ref($conf) ;
foreach my $Key ( keys %$def ) { $$conf{$Key} = $$def{$Key} if !exists $$conf{$Key} ;}
my $layer_conf = {nodes=>1 , persistent_activation=>0 , decay=>0 , random_activation=>0 , threshold=>0 , activation_function=>'tanh' , random_weights=>1} ;
foreach my $Key ( keys %$layer_conf ) { $$layer_conf{$Key} = $$conf{$Key} if exists $$conf{$Key} ;}
return $layer_conf ;
}
sub reset_nn {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
$this->{NN} = AI::NNEasy::NN->new( @{ $this->{NN_ARGS} } ) ;
}
sub load {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $file = shift(@_) ;
$file ||= $this->{FILE} ;
if ( -s $file ) {
open (my $fh, $file) ;
my $dump = join '' , <$fh> ;
close ($fh) ;
my $restored = thaw($dump) ;
lib/AI/NNEasy.pm view on Meta::CPAN
my $fl = $this->{FILE} ;
%$this = %$restored ;
$this->{FILE} = $fl if $fl ;
return 1 ;
}
}
return ;
}
sub save {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $file = shift(@_) ;
$file ||= $this->{FILE} ;
my $dump = freeze( {%$this} ) ;
open (my $fh,">$this->{FILE}") ;
print $fh $dump ;
close ($fh) ;
}
sub learn {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $in = shift(@_) ;
my $out = shift(@_) ;
my $n = shift(@_) ;
$n ||= 100 ;
my $err ;
for (1..100) {
$this->{NN}->run($in) ;
$err = $this->{NN}->learn($out) ;
}
$err *= -1 if $err < 0 ;
return $err ;
}
*_learn_set_get_output_error = \&_learn_set_get_output_error_c ;
sub _learn_set_get_output_error_pl {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $set = shift(@_) ;
my $error_ok = shift(@_) ;
my $ins_ok = shift(@_) ;
my $verbose = shift(@_) ;
for (my $i = 0 ; $i < @$set ; $i+=2) {
$this->{NN}->run($$set[$i]) ;
$this->{NN}->learn($$set[$i+1]) ;
}
lib/AI/NNEasy.pm view on Meta::CPAN
$err /= $ins_ok ;
return ( $err , $learn_ok , $print ) ;
}
sub learn_set {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my @set = ref($_[0]) eq 'ARRAY' ? @{ shift(@_) } : ( ref($_[0]) eq 'HASH' ? %{ shift(@_) } : shift(@_) ) ;
my $ins_ok = shift(@_) ;
my $limit = shift(@_) ;
my $verbose = shift(@_) ;
my $ins_sz = @set / 2 ;
$ins_ok ||= $ins_sz ;
lib/AI/NNEasy.pm view on Meta::CPAN
}
}
print "epoch $counter : error = $err : ok = $learn_ok\n" if $verbose > 1 ;
}
}
sub get_set_error {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my @set = ref($_[0]) eq 'ARRAY' ? @{ shift(@_) } : ( ref($_[0]) eq 'HASH' ? %{ shift(@_) } : shift(@_) ) ;
my $ins_ok = shift(@_) ;
my $ins_sz = @set / 2 ;
$ins_ok ||= $ins_sz ;
my $err ;
for (my $i = 0 ; $i < @set ; $i+=2) {
lib/AI/NNEasy.pm view on Meta::CPAN
my $er = $this->{NN}->RMSErr($set[$i+1]) ;
$er *= -1 if $er < 0 ;
$err += $er ;
}
$err /= $ins_ok ;
return $err ;
}
sub run {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $in = shift(@_) ;
$this->{NN}->run($in) ;
my $out = $this->{NN}->output() ;
return $out ;
}
sub run_get_winner {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $out = $this->run(@_) ;
foreach my $out_i ( @$out ) {
$out_i = $this->out_type_winner($out_i) ;
}
return $out ;
}
sub out_type_winner {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $val = shift(@_) ;
my ($out_type , %err) ;
foreach my $types_i ( @{ $this->{OUT_TYPES} } ) {
my $er = $types_i - $val ;
$er *= -1 if $er < 0 ;
$err{$types_i} = $er ;
}
lib/AI/NNEasy/NN.pm view on Meta::CPAN
use Class::HPLOO::Base ;
use AI::NNEasy::NN::layer ;
use AI::NNEasy::NN::feedforward ;
use AI::NNEasy::NN::backprop ;
use vars qw($AUTOLOAD) ;
sub NN {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $params = shift(@_) ;
my $netParams = shift(@_) ;
my @layers ;
foreach my $i (keys %$netParams) {
$this->{$i} = $$netParams{$i};
}
lib/AI/NNEasy/NN.pm view on Meta::CPAN
$this->{biasNode} = AI::NNEasy::NN::node->new( {activation_function => 'linear'} ) ;
$this->{biasNode}->{activation} = 1;
}
$this->init ;
return $this ;
}
sub init {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my @layers = @{$this->{layers}} ;
my $currentLayer ;
foreach my $layer (@layers) {
# Foreach node we need to make connections east and west
foreach my $node ( @{$layer->{nodes}} ) {
# only initialise to the west if layer > 0
lib/AI/NNEasy/NN.pm view on Meta::CPAN
foreach my $node (@{$layer->{nodes}}) {
push @{$node->{connectedNodesWest}->{nodes}},$this->{biasNode};
my $weight = $this->{random_weights} ? rand(1) : 0 ;
$node->{connectedNodesWest}->{weights}{ $this->{biasNode}->{nodeid} } = $weight ;
}
}
}
}
sub learn {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
&{$this->{learning_algorithm_class} . '::learn'}($this , @_) ;
}
sub output {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $params = shift(@_) ;
my $outputLayer = defined $$params{layer} ? $this->{layers}[$$params{layer}] : $this->{layers}[-1] ;
return AI::NNEasy::NN::layer::layer_output($outputLayer) ;
}
sub linear { my $this = ref($_[0]) ? shift : undef ;my $CLASS = ref($this) || __PACKAGE__ ;my $value = shift(@_) ; return $value ;}
*tanh = \&tanh_c ;
sub tanh_pl {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $value = shift(@_) ;
if ($value > 20) { return 1 ;}
elsif ($value < -20) { return -1 ;}
else {
my $x = exp($value) ;
my $y = exp(-$value) ;
return ($x-$y)/($x+$y) ;
}
}
*sigmoid = \&sigmoid_c ;
sub sigmoid_pl {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $value = shift(@_) ;
return (1+exp(-$value))**-1 ;
}
sub AUTOLOAD {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my ($name) = ( $AUTOLOAD =~ /(\w+)$/ ) ;
my $sub = $this->{learning_algorithm_class} . '::' . $name ;
return &$sub($this,@_) if defined &$sub ;
my @call = caller ;
die("Can't find $AUTOLOAD or $sub at @call\n") ;
}
my $INLINE_INSTALL ; BEGIN { use Config ; my @installs = ($Config{installarchlib} , $Config{installprivlib} , $Config{installsitelib}) ; foreach my $i ( @installs ) { $i =~ s/[\\\/]/\//gs ;} $INLINE_INSTALL = 1 if ( __FILE__ =~ /\.pm$/ && ( join(" ",...
lib/AI/NNEasy/NN/backprop.pm view on Meta::CPAN
my $CLASS = 'AI::NNEasy::NN::backprop' ; sub __CLASS__ { 'AI::NNEasy::NN::backprop' } ;
use Class::HPLOO::Base ;
sub calc_error {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $outputPatternRef = shift(@_) ;
my @outputPattern = @$outputPatternRef;
my $outputLayer = $this->{layers}->[-1]->{nodes} ;
return 0 if @$outputLayer != @outputPattern ;
my $counter = 0 ;
foreach my $node (@$outputLayer) {
$node->{error} = $node->{activation} - $outputPattern[$counter] ;
++$counter ;
}
}
sub learn {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $outputPatternRef = shift(@_) ;
$this->calc_error($outputPatternRef) ;
$this->hiddenToOutput ;
$this->hiddenOrInputToHidden if @{$this->{layers}} > 2 ;
return $this->RMSErr($outputPatternRef) ;
}
*hiddenToOutput = \&hiddenToOutput_c ;
sub hiddenToOutput_pl {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
foreach my $node ( @{ $this->{layers}->[-1]->{nodes} } ) {
foreach my $connectedNode ( @{$node->{connectedNodesWest}->{nodes}} ) {
$node->{connectedNodesWest}->{weights}->{ $connectedNode->{nodeid} } -= $this->{learning_rate} * $node->{error} * $connectedNode->{activation} ;
$node->{connectedNodesWest}->{weights}->{ $connectedNode->{nodeid} } = 5 if $node->{connectedNodesWest}->{weights}->{ $connectedNode->{nodeid} } > 5 ;
$node->{connectedNodesWest}->{weights}->{ $connectedNode->{nodeid} } = -5 if $node->{connectedNodesWest}->{weights}->{ $connectedNode->{nodeid} } < -5 ;
}
}
}
*hiddenOrInputToHidden = \&hiddenOrInputToHidden_c ;
sub hiddenOrInputToHidden_pl {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my ( $nodeid , $nodeError , $nodeActivation ) ;
my $learningRate = $this->{learning_rate} ;
foreach my $layer ( reverse @{$this->{layers}}[0 .. $#{$this->{layers}}-1 ] ) {
foreach my $node ( @{$layer->{nodes}} ) {
last if !$node->{connectedNodesWest} ;
lib/AI/NNEasy/NN/backprop.pm view on Meta::CPAN
}
}
}
*RMSErr = \&RMSErr_c ;
sub RMSErr_pl {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $outputPatternRef = shift(@_) ;
my $outputLayer = $this->{layers}->[-1]->{nodes} ;
my $sqrErr ;
my $counter = 0 ;
foreach my $node (@$outputLayer) {
$sqrErr += ($node->{activation} - $$outputPatternRef[$counter])**2 ;
++$counter ;
lib/AI/NNEasy/NN/feedforward.pm view on Meta::CPAN
my $CLASS = 'AI::NNEasy::NN::feedforward' ; sub __CLASS__ { 'AI::NNEasy::NN::feedforward' } ;
use Class::HPLOO::Base ;
*run = \&run_c ;
sub run_pl {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $inputPatternRef = shift(@_) ;
# Now apply the activation
my $counter = 0 ;
foreach my $node ( @{ $this->{layers}->[0]->{nodes} } ) {
if ( $node->{active} ) {
if ( $node->{persistent_activation} ) {
$node->{activation} += $$inputPatternRef[$counter] ;
}
lib/AI/NNEasy/NN/layer.pm view on Meta::CPAN
@ISA = qw(Class::HPLOO::Base UNIVERSAL) ;
my $CLASS = 'AI::NNEasy::NN::layer' ; sub __CLASS__ { 'AI::NNEasy::NN::layer' } ;
use Class::HPLOO::Base ;
use AI::NNEasy::NN::node ;
sub layer {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $params = shift(@_) ;
$this->{nodes} = [] ;
for (1 .. $$params{nodes}) { push( @{$this->{nodes}} , AI::NNEasy::NN::node->new($params) ) ;}
return $this ;
}
sub layer_output {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $params = shift(@_) ;
my @outputs ;
foreach my $node ( @{$this->{nodes}} ) {
push(@outputs , $$node{activation}) ;
}
return \@outputs;
}
lib/AI/NNEasy/NN/node.pm view on Meta::CPAN
@ISA = qw(Class::HPLOO::Base UNIVERSAL) ;
my $CLASS = 'AI::NNEasy::NN::node' ; sub __CLASS__ { 'AI::NNEasy::NN::node' } ;
use Class::HPLOO::Base ;
my $NODEID ;
sub node {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
my $params = shift(@_) ;
$this->{nodeid} = ++$NODEID ;
$this->{activation} = $$params{random_activation} ? rand($$params{random}) : 0 ;
$this->{random_weights} = $$params{random_weights} ;
$this->{decay} = $$params{decay} ;
$this->{adjust_error} = $$params{adjust_error} ;
lib/AI/NNEasy/NN/reinforce.pm view on Meta::CPAN
use vars qw(%CLASS_HPLOO @ISA) ;
@ISA = qw(Class::HPLOO::Base UNIVERSAL) ;
my $CLASS = 'AI::NNEasy::NN::reinforce' ; sub __CLASS__ { 'AI::NNEasy::NN::reinforce' } ;
use Class::HPLOO::Base ;
sub learn {
my $this = ref($_[0]) ? shift : undef ;
my $CLASS = ref($this) || __PACKAGE__ ;
foreach my $layer ( reverse @{$this->{'layers'}}[ 1 .. $#{$this->{'layers'}} ] ) {
foreach my $node ( @{$layer->{nodes}} ) {
foreach my $westNode ( @{$node->{connectedNodesWest}->{nodes}} ) {
my $dW = $westNode->{activation} * $node->{connectedNodesWest}->{weights}->{ $westNode->{nodeid} } * $this->{learning_rate} ;
$node->{connectedNodesWest}->{weights}->{ $westNode->{nodeid} } += $dW ;
}
}
}
samples/test-nn-nonbool.pl view on Meta::CPAN
[0.5,0] => [0.6],
[0.5,0.5] => [0.8],
[0.5,1] => [1],
);
my $set_err = $nn->get_set_error(\@set) ;
print "SET ERROR NOW: $set_err\n" ;
while ( $set_err > $nn->{ERROR_OK} ) {
$nn->learn_set( \@set , undef , undef , 1) ;
$set_err = $nn->get_set_error(\@set) ;
}
$nn->save ;
print "-------------------------------------------\n" ;
print "ERR_OK: $nn->{ERROR_OK}\n" ;
print "-------------------------------------------\n" ;
samples/test-nn-xor.pl view on Meta::CPAN
[0,1] => [1],
[1,0] => [1],
[1,1] => [0],
);
my $set_err = $nn->get_set_error(\@set) ;
print "SET ERROR NOW: $set_err\n" ;
while ( $set_err > $nn->{ERROR_OK} ) {
$nn->learn_set( \@set , undef , undef , 1) ;
$set_err = $nn->get_set_error(\@set) ;
}
$nn->save ;
print "-------------------------------------------\n" ;
print "ERR_OK: $nn->{ERROR_OK}\n" ;
print "-------------------------------------------\n" ;