Algorithm-Classifier-IsolationForest
view release on metacpan or search on metacpan
lib/Algorithm/Classifier/IsolationForest/App/Command/stream.pm view on Meta::CPAN
} ## end if ( !$oif )
# Munge the raw rows into numbers, then run the numeric validation
# that was skipped at read time. Munged into a separate structure so
# -d still prints the raw input columns as given.
my $stream_rows = \@data;
if ($has_mungers) {
my $munged = $oif->munge_rows( \@data );
for my $i ( 0 .. $#$munged ) {
for my $col ( 0 .. $#{ $munged->[$i] } ) {
die( 'Line '
. ( $i + 1 ) . ' of "'
. $opt->{'i'}
. '" value for column '
. ( $col + 1 ) . ',"'
. ( defined $munged->[$i][$col] ? $munged->[$i][$col] : 'undef' )
. '", is not a number after munging' )
unless looks_like_number( $munged->[$i][$col] );
} ## end for my $col ( 0 .. $#{ $munged->[$i] } )
} ## end for my $i ( 0 .. $#$munged )
$stream_rows = $munged;
} ## end if ($has_mungers)
# --- stream ------------------------------------------------------------
my $results_string = '';
if ( $opt->{'learn_only'} ) {
$oif->learn($stream_rows);
} else {
my $scores;
if ( $opt->{'score_only'} ) {
$scores = $oif->score_samples($stream_rows);
} else {
$scores = $oif->score_learn($stream_rows);
}
my $threshold
= defined $opt->{'threshold'} ? $opt->{'threshold'}
: defined $oif->decision_threshold ? $oif->decision_threshold
: 0.5;
for my $i ( 0 .. $#$scores ) {
my $label = $scores->[$i] >= $threshold ? 1 : 0;
if ( $opt->{'d'} ) {
$results_string .= join( ',', @{ $data[$i] } ) . ',' . $scores->[$i] . ',' . $label . "\n";
} else {
$results_string .= $scores->[$i] . ',' . $label . "\n";
}
}
} ## end else [ if ( $opt->{'learn_only'} ) ]
# Refresh the contamination threshold against the post-stream window so
# the saved model's default cutoff tracks the stream.
if ( !$opt->{'score_only'} && defined $oif->{contamination} && $oif->window_count ) {
$oif->relearn_threshold;
}
if ( $opt->{'save'} && !$opt->{'score_only'} ) {
$oif->save( $opt->{'m'} );
}
if ( length $results_string ) {
if ( !defined( $opt->{'o'} ) ) {
print $results_string;
} else {
write_file( $opt->{'o'}, { 'atomic' => 1 }, $results_string );
}
}
return 1;
} ## end sub execute
=head1 NAME
Algorithm::Classifier::IsolationForest::App::Command::stream - Stream CSV rows through an Online Isolation Forest model, scoring and learning as it goes
=head1 DESCRIPTION
Streams the input rows, in order, through an
L<Algorithm::Classifier::IsolationForest::Online> model.
The default is prequential: each row is scored against the model as it
stood before that row was learned, then learned, and the model state --
sliding window included -- is saved back to C<-m>, so the next invocation
resumes the stream where this one left off. C<--learn-only> skips the
scoring, which is what a warm-up wants; C<--score-only> skips the
learning.
When C<-m> does not exist yet the creation knobs build a new model; when
it does exist they are ignored. With C<--prototype> the schema and its
version and description come from the prototype file, its params supply
the knob defaults, and the other creation switches override those params.
Input matches C<iforest fit>: CSV, every column a numeric feature, one
sample per row. Output is one line per input row:
$score,$label
With C<-d> the input feature columns are prepended.
Run it as C<iforest stream>; C<iforest help stream> lists every option.
=head1 METHODS
L<App::Cmd> calls these while dispatching the subcommand. Nothing else
should.
=head2 opt_spec
Returns this command's option specifications, as the list of arrayrefs
L<Getopt::Long::Descriptive> expects.
=head2 abstract
Returns the one-line summary C<iforest commands> prints beside the
command name.
=head2 description
Returns the long help text C<iforest help stream> prints under the option
list.
( run in 2.284 seconds using v1.01-cache-2.11-cpan-54e63673c56 )