Algorithm-Classifier-IsolationForest
view release on metacpan or search on metacpan
lib/Algorithm/Classifier/IsolationForest.pm view on Meta::CPAN
online => { map { $_ => 1 } qw(n_trees window_size max_leaf_samples growth subsample contamination seed) },
);
my %PROTO_SCHEMA_KEYS = (
batch => { map { $_ => 1 } qw(feature_names feature_descriptions mungers missing impute_with) },
online => { map { $_ => 1 } qw(feature_names feature_descriptions mungers missing) },
);
=head2 validate_prototype($proto)
Structurally validates a prototype -- a hashref or a JSON string -- and
returns the decoded hashref; croaks describing the first problem found.
Validation is structural only (no munger compilation), so it does not
require Algorithm::ToNumberMunger even for a munger-bearing prototype.
my $proto = Algorithm::Classifier::IsolationForest->validate_prototype($json);
=cut
sub validate_prototype {
my ( $class, $proto ) = @_;
if ( !ref $proto ) {
my $decoded = eval { JSON::PP->new->decode($proto) };
croak "prototype did not parse as JSON: $@" if $@;
$proto = $decoded;
}
croak "not an IsolationForest prototype (expected a JSON object)"
unless ref $proto eq 'HASH';
croak "not an IsolationForest prototype (format is not " . "'Algorithm::Classifier::IsolationForest::Prototype')"
unless defined $proto->{format}
&& !ref $proto->{format}
&& $proto->{format} eq 'Algorithm::Classifier::IsolationForest::Prototype';
my $version = $proto->{version} // 1;
croak "prototype format version '$version' is newer than this module understands (max 1)"
lib/Algorithm/Classifier/IsolationForest/App/Command/fit.pm view on Meta::CPAN
} ## end sub validate
sub execute {
my ( $self, $opt, $args ) = @_;
my $mode = 'axis';
if ( $opt->{'extended'} ) {
$mode = 'extended';
}
# Munger spec, decoded up front so a bad file dies before the CSV is
# read. With mungers active the per-field numeric check is skipped
# during the read (munged columns legitimately hold raw strings) and
# re-run after munging instead.
my $mungers;
if ( defined( $opt->{'mungers'} ) ) {
require JSON::PP;
$mungers = eval { JSON::PP->new->decode( scalar read_file( $opt->{'mungers'} ) ) };
die( '--mungers, "' . $opt->{'mungers'} . '", did not parse as JSON: ' . $@ ) if $@;
die( '--mungers, "' . $opt->{'mungers'} . '", must be a JSON object of tag => spec' )
unless ref $mungers eq 'HASH';
lib/Algorithm/Classifier/IsolationForest/App/Command/streamc.pm view on Meta::CPAN
# -o accumulates and writes atomically at the end (matching `iforest
# stream`), so it is unsuitable for an endless stdin; without it,
# results print as replies arrive.
my $results = '';
my $emit = sub {
if ( defined $opt->{'o'} ) { $results .= $_[0] . "\n" }
else { print $_[0] . "\n" }
};
my $expected_cols;
my @rows; # decoded rows for the pending request
my @raw; # matching raw input lines, for -d
my $batch_start = 1; # input line number of $rows[0]
my $line_int = 0;
my $flush = sub {
return unless @rows;
my $got = _request( { rows => [@rows], mode => $opt->{'mode'}, tag => $batch_start } );
my $reply = $got->{reply};
if ( defined $reply->{error} ) {
my $line = $batch_start;
t/42-prototype.t view on Meta::CPAN
);
}; ## end 'load_prototype and persistence of the schema metadata' => sub
subtest 'to_prototype extraction round trip' => sub {
my $data = do { srand(13); rows(150) };
my $a = $batch_class->new_from_prototype( proto_batch(), seed => 42, contamination => 0.1 );
$a->fit($data);
my $extracted = $a->to_prototype;
my $decoded = $batch_class->validate_prototype($extracted);
is( $decoded->{class}, 'batch', 'extracted prototype is valid and batch' );
is( $decoded->{schema_version}, 'b1', 'extracted prototype keeps the schema_version' );
is( $decoded->{params}{contamination}, 0.1, 'override made it into the extracted params' );
# Recreate from the extraction with the same seed: identical model.
my $b = $batch_class->new_from_prototype( $extracted, seed => 42 );
$b->fit($data);
is( $b->to_json, $a->to_json, 'model recreated from the extracted prototype is byte-identical' );
# Online extraction round-trips through the validator too.
my $o = $batch_class->new_from_prototype( proto_online() );
my $op = $batch_class->validate_prototype( $o->to_prototype );
is( $op->{class}, 'online', 'online extraction carries class online' );
t/91-streamd.t view on Meta::CPAN
my $left = $deadline - time;
return undef if $left <= 0 || !$sel->can_read($left);
my $got = sysread( $s, my $chunk, 65536 );
return undef unless $got;
$$buf .= $chunk;
}
$$buf =~ s/\A([^\n]*)\n//;
return $JSON->decode($1);
} ## end sub read_reply
# One request in, one decoded reply out.
sub rt {
my ( $s, $msg ) = @_;
print {$s} $JSON->encode($msg) . "\n";
return read_reply($s);
}
my $daemon = start_daemon(
'--save-interval' => 1,
'-n' => 20,
'--window' => 64,
( run in 0.522 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )