AI-Perceptron

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

               ->weights([ 0.1, 0.2 ]);

     my @inputs  = ( 1.3, -0.45 );   # input can be any number
     my $target  = 1;                # output is always -1 or 1
     my $current = $p->compute_output( @inputs );

     print "current output: $current, target: $target\n";

     $p->add_examples( [ $target, @inputs ] );

     $p->max_iterations( 10 )->train or
       warn "couldn't train in 10 iterations!";

     print "training until it gets it right\n";
     $p->max_iterations( -1 )->train; # watch out for infinite loops

DESCRIPTION
    This module is meant to show how a single node of a neural network
    works.

    Training is done by the *Stochastic Approximation of the
    Gradient-Descent* model.

MODEL
    Model of a Perceptron

README  view on Meta::CPAN

            update weights for each example that fails

    The value each weight is adjusted by is calculated as follows:

        delta[i] = learning_rate * (expected_output - output) * input[i]

    Which is know as a negative feedback loop - it uses the current output
    as an input to determine what the next output will be.

    Also, note that this means you can get stuck in an infinite loop. It's
    not a bad idea to set the maximum number of iterations to prevent that.

CONSTRUCTOR
    new( [%args] )
        Creates a new perceptron with the following default properties:

            num_inputs    = 1
            learning_rate = 0.01
            threshold     = 0.0
            weights       = empty list

README  view on Meta::CPAN


    threshold( [ $float ] )
        Set/get the perceptron's number of inputs.

    training_examples( [ \@examples ] )
        Set/get the perceptron's list of training examples. This should be a
        list of arrayrefs of the form:

            [ $expected_result => @inputs ]

    max_iterations( [ $int ] )
        Set/get the perceptron's number of inputs, a negative value implies
        no maximum.

METHODS
    compute_output( @inputs )
        Computes and returns the perceptron's output (either -1 or 1) for
        the given inputs. See the above model for more details.

    add_examples( @training_examples )
        Adds the @training_examples to to current list of examples. See

lib/AI/Perceptron.pm  view on Meta::CPAN

           ->weights([ 0.1, 0.2 ]);

 my @inputs  = ( 1.3, -0.45 );   # input can be any number
 my $target  = 1;                # output is always -1 or 1
 my $current = $p->compute_output( @inputs );

 print "current output: $current, target: $target\n";

 $p->add_examples( [ $target, @inputs ] );

 $p->max_iterations( 10 )->train or
   warn "couldn't train in 10 iterations!";

 print "training until it gets it right\n";
 $p->max_iterations( -1 )->train; # watch out for infinite loops

=cut

package AI::Perceptron;

use strict;
use accessors qw( num_inputs learning_rate _weights threshold
		  training_examples max_iterations );

our $VERSION = '1.0';
our $Debug   = 0;

sub new {
    my $class = shift;
    my $self  = bless {}, $class;
    return $self->init( @_ );
}

sub init {
    my $self = shift;
    my %args = @_;

    $self->num_inputs( $args{Inputs} || 1 )
         ->learning_rate( $args{N} || 0.05 )
	 ->max_iterations( -1 )
	 ->threshold( $args{T} || 0.0 )
	 ->training_examples( [] )
	 ->weights( [] );

    # DEPRECATED: backwards compat
    if ($args{W}) {
	$self->threshold( shift @{ $args{W} } )
	     ->weights( [ @{ $args{W} } ] );
    }

lib/AI/Perceptron.pm  view on Meta::CPAN

    my $self = shift;
    $self->add_examples( @_ ) if @_;

    $self->verify_weights;

    # adjust the weights for each training example until the output
    # function correctly classifies all the training examples.
    my $iter = 0;
    while(! $self->classifies_examples_correctly ) {

	if (($self->max_iterations > 0) and
	    ($iter >= $self->max_iterations)) {
	    $self->emit( "stopped training after $iter iterations" );
	    return;
	}

	$iter++;
	$self->emit( "Training iteration $iter" );

	foreach my $training_example (@{ $self->training_examples }) {
	    my ($expected_output, @inputs) = @$training_example;

	    $self->emit( "Training X=<", join(',', @inputs),

lib/AI/Perceptron.pm  view on Meta::CPAN

	    # want the perceptron's output equal to training output
	    # TODO: this duplicates work by classifies_examples_correctly()
	    my $output = $self->compute_output(@inputs);
	    next if ($output == $expected_output);

	    $self->adjust_threshold( $expected_output, $output )
	         ->adjust_weights( \@inputs, $expected_output, $output );
	}
    }

    $self->emit( "completed in $iter iterations." );

    return $self;
}

# return true unless all training examples are correctly classified
sub classifies_examples_correctly {
    my $self = shift;
    my $training_examples = $self->training_examples;

    foreach my $training_example (@$training_examples) {

lib/AI/Perceptron.pm  view on Meta::CPAN

        update weights for each example that fails

The value each weight is adjusted by is calculated as follows:

    delta[i] = learning_rate * (expected_output - output) * input[i]

Which is know as a negative feedback loop - it uses the current output as an
input to determine what the next output will be.

Also, note that this means you can get stuck in an infinite loop.  It's not a
bad idea to set the maximum number of iterations to prevent that.

=head1 CONSTRUCTOR

=over 4

=item new( [%args] )

Creates a new perceptron with the following default properties:

    num_inputs    = 1

lib/AI/Perceptron.pm  view on Meta::CPAN


Set/get the perceptron's number of inputs.

=item training_examples( [ \@examples ] )

Set/get the perceptron's list of training examples.  This should be a list of
arrayrefs of the form:

    [ $expected_result => @inputs ]

=item max_iterations( [ $int ] )

Set/get the perceptron's number of inputs, a negative value implies no maximum.

=back

=head1 METHODS

=over 4

=item compute_output( @inputs )

t/01_basic.t  view on Meta::CPAN


use Test::More 'no_plan'; # tests => 3;

use_ok( 'AI::Perceptron' );

my $p = AI::Perceptron->new
          ->num_inputs( 2 )
          ->learning_rate( 0.01 )
          ->threshold( 0.8 )
          ->weights([ -0.5, 0.5 ])
          ->max_iterations( 20 );

# get the current output of the node given a training example:
my @inputs = ( 1, 1 );
my $target_output  = 1;
my $current_output = $p->compute_output( @inputs );

ok( defined $current_output,         'compute_output' );
is( $current_output, $target_output, 'expected output for preset weights' );

# train the perceptron until it gets it right:

t/02_api.t  view on Meta::CPAN


use Test::More 'no_plan'; # tests => 3;

use AI::Perceptron;

my $p = AI::Perceptron->new
                      ->num_inputs( 3 )
                      ->learning_rate( 0.01 )
                      ->threshold( 0.02 )
                      ->weights([ 0.1, 0.2, -0.3 ])
                      ->max_iterations( 5 )
                      ->training_examples( [ -1 => 1, 2 ] );

is( $p->num_inputs,             3,      'num_inputs' );
is( $p->learning_rate,          0.01,   'learning_rate' );
is( $p->threshold,              0.02,   'threshold' );
is( $p->max_iterations,         5,      'threshold' );
isa_ok( $p->weights,           'ARRAY', 'weights' );
isa_ok( $p->training_examples, 'ARRAY', 'examples' );

is( $p->add_examples( [-1 => 1, 1] ), $p, 'add_examples' );
can_ok( $p, 'add_example',                'add_example' );

##
## backwards compat
##



( run in 0.651 second using v1.01-cache-2.11-cpan-96521ef73a4 )