use
t::TestAM
qw(chapter_3_train chapter_3_test)
;
my
%hook_calls
= (
begin_hook
=> 1,
begin_test_hook
=> 2,
begin_repeat_hook
=> 4,
end_repeat_hook
=> 4,
training_item_hook
=> 20,
end_test_hook
=> 2,
end_hook
=> 1,
);
my
$total_calls
= 0;
$total_calls
+=
$_
for
values
%hook_calls
;
plan
tests
=>
$total_calls
+ 1*2 + 2 + 1;
my
%tests_per_sub
= (
test_beginning_vars
=> 5,
test_item_vars
=> 4,
test_iter_vars
=> 1,
test_training_item_hook_vars
=> 2,
test_end_iter_vars
=> 2,
test_end_test_vars
=> 3,
test_end_vars
=> 4
);
my
%test_subs
= (
test_beginning_vars
=> \
&test_beginning_vars
,
test_item_vars
=> \
&test_item_vars
,
test_iter_vars
=> \
&test_iter_vars
,
test_training_item_hook_vars
=> \
&test_training_item_hook_vars
,
test_end_iter_vars
=> \
&test_end_iter_vars
,
test_end_test_vars
=> \
&test_end_test_vars
,
test_end_vars
=> \
&test_end_vars
);
my
$train
= chapter_3_train();
my
$test
= chapter_3_test();
$test
->add_item(
features
=> [
qw(3 1 3)
],
comment
=>
'second test item'
,
class
=>
'e'
,
);
my
$batch
= Algorithm::AM::Batch->new(
training_set
=>
$train
,
repeat
=> 2,
max_training_items
=> 10,
begin_hook
=> make_hook(
'begin_hook'
,
'test_beginning_vars'
),
begin_test_hook
=> make_hook(
'begin_test_hook'
,
'test_beginning_vars'
,
'test_item_vars'
),
begin_repeat_hook
=> make_hook(
'begin_repeat_hook'
,
'test_beginning_vars'
,
'test_item_vars'
,
'test_iter_vars'
),
training_item_hook
=> make_hook(
'training_item_hook'
,
'test_beginning_vars'
,
'test_item_vars'
,
'test_iter_vars'
,
'test_training_item_hook_vars'
),
end_repeat_hook
=> make_hook(
'end_repeat_hook'
,
'test_beginning_vars'
,
'test_item_vars'
,
'test_iter_vars'
,
'test_end_iter_vars'
),
end_test_hook
=> make_hook(
'end_test_hook'
,
'test_beginning_vars'
,
'test_item_vars'
,
'test_end_test_vars'
),
end_hook
=> make_hook(
'end_hook'
,
'test_beginning_vars'
,
'test_end_vars'
),
);
test_defaults(
$batch
);
$batch
->classify_all(
$test
);
test_defaults(
$batch
);
test_training_item_hook();
sub
make_hook {
my
(
$name
,
@subs
) =
@_
;
return
sub
{
my
(
@args
) =
@_
;
subtest
$name
=>
sub
{
my
$plan
= 0;
$plan
+=
$tests_per_sub
{
$_
}
for
@subs
;
plan
tests
=>
$plan
;
$test_subs
{
$_
}->(
@args
)
for
@subs
;
};
return
1;
};
}
sub
test_beginning_vars {
my
(
$batch
) =
@_
;
isa_ok(
$batch
,
'Algorithm::AM::Batch'
);
is(
$batch
->training_set->size, 5,
'training set'
);
is(
$batch
->test_set->size, 2,
'test set'
);
is(
$batch
->probability, 1,
'probability is 1 by default'
);
is(
$batch
->max_training_items, 10,
'training set capped at 10 items'
);
return
;
}
sub
test_item_vars {
my
(
$batch
,
$test_item
) =
@_
;
isa_ok(
$test_item
,
'Algorithm::AM::DataSet::Item'
);
ok(
$test_item
->class eq
'r'
||
$test_item
->class eq
'e'
,
'test class'
);
if
(
$test_item
->class eq
'e'
){
like(
$test_item
->comment,
qr/second test item$/
,
'test comment'
);
is_deeply(
$test_item
->features, [3,1,3],
'test item features'
)
or note explain
$test_item
->features;
}
else
{
like(
$test_item
->comment,
qr/test item comment$/
,
'test comment'
);
is_deeply(
$test_item
->features, [3,1,2],
'test item features'
)
or note explain
$test_item
->features;
}
return
;
}
sub
test_iter_vars {
my
(
$batch
,
$test_item
,
$iteration
) =
@_
;
ok(
$iteration
== 1 ||
$iteration
== 2,
'only do 2 iteration of classification'
);
return
;
}
sub
test_training_item_hook_vars {
my
(
$batch
,
$test_item
,
$iteration
,
$train_item
) =
@_
;
isa_ok(
$train_item
,
'Algorithm::AM::DataSet::Item'
);
ok(
$train_item
->comment =~ /
my
.
*CommentHere
/,
'item is from training set'
);
}
sub
test_end_iter_vars {
my
(
$batch
,
$test_item
,
$iteration
,
$excluded_items
,
$result
) =
@_
;
if
(
$test_item
->class eq
'e'
){
is_deeply(
$result
->scores, {
e
=>
'4'
,
r
=>
'4'
},
'class scores'
);
}
else
{
is_deeply(
$result
->scores, {
e
=>
'4'
,
r
=>
'9'
},
'classes scores'
);
}
is_deeply(
$excluded_items
, [],
'no items excluded'
);
return
;
}
sub
test_end_test_vars {
my
(
$self
,
$test_item
,
@item_results
) =
@_
;
isa_ok(
$item_results
[0],
'Algorithm::AM::Result'
);
is(
scalar
@item_results
, 2,
'1 result for each iteration'
);
is(
$item_results
[0]->test_item,
$item_results
[0]->test_item,
'results have the same test item'
);
}
sub
test_end_vars {
my
(
$batch
,
@results
) =
@_
;
is_deeply(
$results
[0]->scores, {
e
=>
'4'
,
r
=>
'9'
},
'scores for first result'
);
is_deeply(
$results
[1]->scores, {
e
=>
'4'
,
r
=>
'9'
},
'scores for second result'
);
is_deeply(
$results
[2]->scores, {
e
=>
'4'
,
r
=>
'4'
},
'scores for third result'
);
is_deeply(
$results
[3]->scores, {
e
=>
'4'
,
r
=>
'4'
},
'scores for fourth result'
);
return
;
}
sub
test_defaults {
my
(
$batch
) =
@_
;
is(
$batch
->test_set,
undef
,
'test_set is undef outside of hooks'
);
return
;
}
sub
test_training_item_hook {
my
$batch
= Algorithm::AM::Batch->new(
training_set
=> chapter_3_train(),
training_item_hook
=>
sub
{
return
0;
},
end_repeat_hook
=>
sub
{
my
$excluded_items
=
$_
[3];
is(
scalar
@$excluded_items
, 5,
'training_item_hook excluded all items'
);
isa_ok(
$excluded_items
->[0],
'Algorithm::AM::DataSet::Item'
);
},
);
$batch
->classify_all(chapter_3_test());
return
;
}