AI-MaxEntropy

 view release on metacpan or  search on metacpan

lib/AI/MaxEntropy/Model.pm  view on Meta::CPAN

use strict;
use warnings;

package AI::MaxEntropy::Model;

use YAML::Syck;

our $VERSION = '0.20';

sub new {
    my ($class, $model) = @_;
    my $self = bless {}, $class;
    $self->load($model) if defined($model);
    return $self;
}

sub load {
    my ($self, $file) = @_;
    my $model = LoadFile($file);
    ($self->{x_list}, $self->{y_list}, $self->{f_map}, $self->{lambda})
        = @$model;
    $self->{x_num} = scalar(@{$self->{x_list}});
    $self->{y_num} = scalar(@{$self->{y_list}});
    $self->{f_num} = scalar(@{$self->{lambda}});
    $self->{x_bucket}->{$self->{x_list}->[$_]} = $_
        for (0 .. $self->{x_num} - 1);
    $self->{y_bucket}->{$self->{y_list}->[$_]} = $_
        for (0 .. $self->{y_num} - 1);
}

sub save {
    my ($self, $file) = @_;
    my $data = [
        $self->{x_list},
	$self->{y_list},
	$self->{f_map},
	$self->{lambda}
    ];
    DumpFile($file, $data);    
}

sub all_x { @{$_[0]->{x_list}} }
sub all_labels { @{$_[0]->{y_list}} }

sub score {
    my $self = shift;
    my ($x, $y) = @_;
    # preprocess if $x is hashref
    $x = [
        map {
	    my $attr = $_;
	    ref($x->{$attr}) eq 'ARRAY' ? 
	        map { "$attr:$_" } @{$x->{$attr}} : "$_:$x->{$_}" 
        } keys %$x
    ] if ref($x) eq 'HASH';
    # calculate score
    my @x1 = map { $self->{x_bucket}->{$_} } @$x;
    my $lambda_f = 0;
    if (defined(my $y1 = $self->{y_bucket}->{$y})) {
        for my $x1 (@x1) {
	    if (defined($x1)) {
	        my $lambda_i = $self->{f_map}->[$y1]->[$x1];
                $lambda_f += $self->{lambda}->[$lambda_i]
		    if $lambda_i != -1;
            }
        }
    }
    return $lambda_f; 
}

sub predict {
    my $self = shift;
    my $x = shift;
    my @score = map { $self->score($x => $_) } @{$self->{y_list}};
    my ($max_score, $max_y) = (undef, undef);
    for my $y (0 .. $self->{y_num} - 1) {
        ($max_score, $max_y) = ($score[$y], $y) if not defined($max_y);
	($max_score, $max_y) = ($score[$y], $y) if $score[$y] > $max_score;
    }
    return $self->{y_list}->[$max_y];
}

1;

__END__

=head1 NAME

AI::MaxEntropy::Model - Perl extension for using Maximum Entropy Models

=head1 SYNOPSIS

  use AI::MaxEntropy::Model;

  # learn a model by AI::MaxEntropy
  require AI::MaxEntropy;
  my $me = AI::MaxEntropy->new;
  $me->see(['round', 'smooth', 'red'] => 'apple' => 2);
  $me->see(['long', 'smooth', 'yellow'] => 'banana' => 3);
  $me->see(['round', 'rough'] => 'orange' => 2);
  my $model = $me->learn;

  # make prediction on unseen data
  # ask what a red round thing is most likely to be
  my $y = $model->predict(['round', 'red']);
  # the answer apple is expected

  # print out scores of all possible labels



( run in 0.342 second using v1.01-cache-2.11-cpan-754626df90b )