AI-NNFlex

 view release on metacpan or  search on metacpan

lib/AI/NNFlex/Hopfield.pm  view on Meta::CPAN

}

##########################################################
# AI::NNFlex::Hopfield::run
##########################################################
# apply activation patterns & calculate activation
# through the network
##########################################################
sub run
{
	my $network = shift;

	my $inputPatternRef = shift;

	my @inputpattern = @$inputPatternRef;

	if (scalar @inputpattern != scalar @{$network->{'nodes'}})
	{
		return "Error: input pattern does not match number of nodes"
	}

	# apply the pattern to the network
	my $counter=0;
	foreach my $node (@{$network->{'nodes'}})
	{
		$node->{'activation'} = $inputpattern[$counter];
		$counter++;
	}

	# Now update the network with activation flow
	foreach my $node (@{$network->{'nodes'}})
	{
		$node->{'activation'}=0;
		my $counter=0;
		foreach my $connectedNode (@{$node->{'connectednodes'}->{'nodes'}})
		{
			# hopfield nodes don't have recursive connections
			unless ($node == $connectedNode)
			{
				$node->{'activation'} += $connectedNode->{'activation'} * $node->{'connectednodes'}->{'weights'}->[$counter];

			}
			$counter++;
		}


		# bias
		$node->{'activation'} += 1 * $node->{'connectednodes'}->{'weights'}->[-1];

		my $activationfunction = $node->{'activationfunction'};
		$node->{'activation'} = $network->$activationfunction($node->{'activation'});

	}

	return $network->output;
}

#######################################################
# AI::NNFlex::Hopfield::output
#######################################################
# This needs to be overloaded, because the default
# nnflex output method returns only the rightmost layer
#######################################################
sub output
{
	my $network = shift;

	my @array;
	foreach my $node (@{$network->{'nodes'}})
	{
		unshift @array,$node->{'activation'};
	}

	return \@array;
}

########################################################
# AI::NNFlex::Hopfield::learn
########################################################
sub learn
{
	my $network = shift;

	my $dataset = shift;

	# calculate the weights
	# turn the dataset into a matrix
	my @matrix;
	foreach (@{$dataset->{'data'}})
	{
		push @matrix,$_;
	}
	my $patternmatrix = Math::Matrix->new(@matrix);

	my $inversepattern = $patternmatrix->transpose;

	my @minusmatrix;

	for (my $rows=0;$rows <(scalar @{$network->{'nodes'}});$rows++)
	{
		my @temparray;
		for (my $cols=0;$cols <(scalar	@{$network->{'nodes'}});$cols++)
		{
			if ($rows == $cols)
			{
				my $numpats = scalar @{$dataset->{'data'}};
				push @temparray,$numpats;	
			}
			else
			{
				push @temparray,0;
			}
		}
		push @minusmatrix,\@temparray;
	}

	my $minus = Math::Matrix->new(@minusmatrix);

	my $product = $inversepattern->multiply($patternmatrix);

	my $weights = $product->subtract($minus);



( run in 0.870 second using v1.01-cache-2.11-cpan-39bf76dae61 )