AI::NNFlex::Dataset - support for creating/loading/saving datasets for NNFlex nets


AI-NNFlex documentation Contained in the AI-NNFlex distribution.

Index


Code Index:

NAME

Top

AI::NNFlex::Dataset - support for creating/loading/saving datasets for NNFlex nets

SYNOPSIS

Top

 use AI::NNFlex::Dataset;

 my $dataset = AI::NNFlex::Dataset->new([[0,1,1,0],[0,0,1,1]]);

 $dataset->add([[0,1,0,1],[1,1,0,0]]);

 $dataset->add([0,1,0,0]);

 $dataset->save(filename=>'test.pat');

 $dataset->load(filename=>'test.pat');

DESCRIPTION

Top

This module allows you to construct, load, save and maintain datasets for use with neural nets implemented using the AI::NNFlex classes. The dataset consists of an array of references to arrays of data. Items may be added in pairs (useful for feedforward nets with an input & target pair of values) or individually (for Hopfield type nets where only an input is specified). The load and save methods use files that are compatible (I think) with SNNS .pat files.

CONSTRUCTOR

Top

AI::NNFlex::Dataset->new([[INPUT],[TARGET]]);

Parameters:

The constructor takes an (optional) reference to an array of one or more arrays. For convenience you can specify two values at a time (for INPUT and OUTPUT values) or a single value at a time. You can also leave the parameters blank, in which case the constructor creates a Dataset object with no values. Values can then be added with the 'add' method.

The return value is an AI::NNFlex::Dataset object.

METHODS

Top

This is a short list of the main methods implemented in AI::NNFlex::Dataset

add

 Syntax:

 $dataset->add([[INPUT],[OUTPUT]]);

or

 $dataset->add([VALUE]);

This method adds new values to the end of the dataset. You can specify the values as pairs or individually.

load

 Syntax:

 $dataset->load(filename=>'filename.pat');

Loads an SNNS type .pat file into a blank dataset. If called on an existing dataset IT WILL OVERWRITE IT!

save

 $dataset->save(filename=>'filename.pat');

Save the existing dataset as an SNNS .pat file. If the file already exists it will be overwritten.

delete

 $dataset->delete(INDEX);

or

 $dataset->delete([ARRAY OF INDICES]);

Deletes 1 or more items from the dataset by their index (counting from 0). Note that if you are using pairs of values (in a backprop net for example) you MUST delete in pairs - otherwise you will delete only the input/target, and the indices will be shifted leaving your dataset in a messed up state.

EXAMPLES

Top

See the code in ./examples.

PREREQs

Top

None.

SEE ALSO

Top

 AI::NNFlex




TODO

Top

Method to delete existing dataset entries by index

Method to validate linear separability of a dataset.

CHANGES

Top

COPYRIGHT

Top

CONTACT

Top

 charlesc@nnflex.g0n.net








AI-NNFlex documentation Contained in the AI-NNFlex distribution.

##########################################################
# AI::NNFlex::Dataset
##########################################################
# Dataset methods for AI::NNFlex - perform learning etc
# on groups of data
#
##########################################################
# Versions
# ========
#
# 1.0	20050115	CColbourn	New module
#
# 1.1	20050324	CColbourn	Added load support
#
##########################################################
# ToDo
# ----
#
#
###########################################################
#
use strict;
package AI::NNFlex::Dataset;


###########################################################
# AI::NNFlex::Dataset::new
###########################################################
sub new
{
	my $class = shift;
	my $params = shift;
	my $dataset;
	if ($class =~ /HASH/)
	{
		$dataset = $class;
		$dataset->{'data'} = $params;
		return 1;
	}

	my %attributes;
	$attributes{'data'} = $params;

	$dataset = \%attributes;
	bless $dataset,$class;
	return $dataset;
}


###########################################################
# AI::NNFlex::Datasets::run
###########################################################
sub run
{
	my $self = shift;
	my $network = shift;
	my @outputs;
	my $counter=0;

	for (my $itemCounter=0;$itemCounter<(scalar @{$self->{'data'}});$itemCounter +=2)
	{
		$network->run(@{$self->{'data'}}[$itemCounter]);
		$outputs[$counter] = $network->output();
		$counter++;
	}

	return \@outputs;

}

###############################################################
# AI::NNFlex::Dataset::learn
###############################################################
sub learn
{
	my $self = shift;
	my $network = shift;
	my $error;

	for (my $itemCounter=0;$itemCounter<(scalar @{$self->{'data'}});$itemCounter +=2)
	{
		$network->run(@{$self->{'data'}}[$itemCounter]);
		$error += $network->learn(@{$self->{'data'}}[$itemCounter+1]);
	}

	$error = $error*$error;

	return $error;
}

#################################################################
# AI::NNFlex::Dataset::save
#################################################################
# save a dataset in an snns .pat file
#################################################################
sub save
{
	my $dataset = shift;
	my %config = @_;

	open (OFILE,">".$config{'filename'}) or return "File error $!";

	print OFILE "No. of patterns : ".((scalar @{$dataset->{'data'}})/2)."\n";
	print OFILE "No. of input units : ".(scalar @{$dataset->{'data'}->[0]})."\n";
	print OFILE "No. of output units : ".(scalar @{$dataset->{'data'}->[1]})."\n\n";

	my $counter = 1;
	my @values = @{$dataset->{'data'}};
	while (@values)
	{
		print OFILE "# Input pattern $counter:\n";
		my $input = shift (@values); 
		my @array = join " ",@$input;
		print OFILE @array;
		print OFILE "\n";

		print OFILE "# Output pattern $counter:\n";
		my $output = shift(@values); 
		@array = join " ",@$output;
		print OFILE @array;
		print OFILE "\n";

		$counter++;
	}

	close OFILE;
	return 1;
}


#############################################################
# AI::NNFlex::Dataset::load
#############################################################
sub load
{
	my $dataset = shift;
	my %params = @_;

	my @data;

	my $filename = $params{'filename'};
	if (!$filename)
	{
		return "No filename specified";
	}

	open (IFILE,"$filename") or return "Unable to load $filename - $!";

	my %config;
	# snns pat files have a 3 line header, defining number of patterns &
	# number of input and output units
	my $counter =0;
	while ($counter <3)
	{
		my $line = <IFILE>;
		if ($line =~/^\n/ || $line =~/^#/){next}
		my ($tag,$value) = split/:/,$line;
		$tag=lc($tag);
		$tag =~s/ //g;
		
		$config{lc($tag)} = $value;
		$counter++;
	}

	my $filecontent;
	while (<IFILE>)
	{
		if($_ =~ /^#/ || $_ =~ /^\n/){next}
		$filecontent .= $_;
	}

	my @individualvals = split /\s+/s,$filecontent;

	for (my $offset=0;$offset<(scalar @individualvals);$offset+=($config{'no.ofinputunits'} + $config{'no.ofoutputunits'}))
	{
		my @input=@individualvals[$offset..($offset+$config{'no.ofinputunits'}-1)];
		push @data,\@input;
		if ($config{'no.ofoutputunits'} > 0)
		{
			my @output=@individualvals[($offset+$config{'no.ofinputunits'})..($offset+$config{'no.ofinputunits'}+$config{'no.ofoutputunits'}-1)];
			push @data,\@output;
		}
	}

		
	$dataset->new(\@data);

	return 1;
}
	
##########################################################
# AI::NNFlex::Dataset::add
##########################################################
# add an input/output pair to the dataset
##########################################################
sub add
{
	my $dataset= shift;
	my $params = shift;

	if (!$params){return "Nothing to add"};
	if ($params !~/ARRAY/){return "Need a reference to an array"}

	# support adding single patterns (for Hopfield type nets)
	if ($$params[0] !~ /ARRAY/)
	{
		push @{$dataset->{'data'}},$params;
	}
	else
	{
		push @{$dataset->{'data'}},$$params[0];
		push @{$dataset->{'data'}},$$params[1];
	}

	return 1;
}

##################################################################
# AI::NNFlex::Dataset::delete
##################################################################
# delete an item from the dataset by index
##################################################################
sub delete
{
	my $dataset = shift;
	my $index = shift;
	my @indexarray;

	if (!$index){return 0}

	if ($index =~ /ARRAY/)
	{
		@indexarray = @$index;
	}
	else
	{
		$indexarray[0] = $index;
	}

	my @newarray;
	my $counter=0;
	foreach (@indexarray)
	{
		unless ($counter == $_)
		{
			push @newarray,${$dataset->{'data'}}[$_];
		}
	}

	$dataset->{'data'} = \@newarray;

	return 1;
}



1;