Statis...ingency(3pm)

πŸ“¦
version 0.09 Β· 4 versions
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– Statistics::Contingency πŸ’–

okay bestie, sit down, hydrate, because we're about to talk about a Perl module that is lowkey the moment for anyone judging how good their automatic text categorizer actually is. it's giving math girlie. it's giving contingency tables. it's giving precision, recall, F1, accuracy, etc. and honestly? slay. ✨

the version we're living in is version 0.09, periodt.


✨ SYNOPSIS ✨

here's the whole vibe in one little snippet, no notes:

use Statistics::Contingency;
my $s = new Statistics::Contingency(categories => \@all_categories);

while (...something...) {
  ...
  $s->add_result($assigned_categories, $correct_categories);
}

print "Micro F1: ", $s->micro_F1, "\n"; # Access a single statistic
print $s->stats_table; # Show several stats in table form

like. create the object, dump results into it as they happen, then ask it for numbers. that's the whole relationship. 🫢


🌸 DESCRIPTION 🌸

the Statistics::Contingency class helps you calculate several useful statistical measures based on 2x2 "contingency tables". the author uses these measures to help judge the results of automatic text categorization experiments, but they're useful in other situations too β€” so don't gatekeep, they're for everyone. πŸ’…

the general usage flow is: tally a whole bunch of results in the Statistics::Contingency object, then query that object to obtain the measures you're interested in. once all the results have been collected, you can get a report on accuracy, precision, recall, F1, and so on, with both macro-averaging and micro-averaging over categories. two flavors, both iconic, we love options. πŸŽ€

🌈 Macro vs. Micro Statistics 🌈

all of the statistics offered by this module can be calculated for each category and then averaged, or can be calculated over all decisions and then averaged.

  • the former is called macro-averaging (specifically, macro-averaging with respect to category)
  • the latter is called micro-averaging

the two procedures bias the results differently β€” micro-averaging tends to over-emphasize the performance on the largest categories, while macro-averaging over-emphasizes the performance on the smallest. it's often best to look at both of them to get a good idea of how your data distributes across categories. like, don't pick a favorite, they're both your children. 😭

πŸ¦‹ Statistics available πŸ¦‹

all of the statistics are calculated based on a so-called "contingency table", which looks like this:

              Correct=Y   Correct=N
            +-----------+-----------+
 Assigned=Y |     a     |     b     |
            +-----------+-----------+
 Assigned=N |     c     |     d     |
            +-----------+-----------+

a, b, c, and d are counts that reflect how the assigned categories matched the correct categories. depending on whether a macro-statistic or a micro-statistic is being calculated, these numbers will be tallied per-category or for the entire result set. it's the same little grid either way, just wearing a different outfit. ✨

the following statistics are available:

  • accuracy β€” this measures the portion of all decisions that were correct decisions. it is defined as (a+d)/(a+b+c+d). it falls in the range from 0 to 1, with 1 being the best score. and heads up: macro-accuracy and micro-accuracy will always give the same number. always. no cap. πŸ‘‘
  • error β€” this measures the portion of all decisions that were incorrect decisions. it is defined as (b+c)/(a+b+c+d). it falls in the range from 0 to 1, with 0 being the best score. also, macro-error and micro-error will always give the same number. twin behavior fr fr.
  • precision β€” this measures the portion of the assigned categories that were correct. it is defined as a/(a+b). it falls in the range from 0 to 1, with 1 being the best score. πŸ’–
  • recall β€” this measures the portion of the correct categories that were assigned. it is defined as a/(a+c). it falls in the range from 0 to 1, with 1 being the best score. 🌸
  • F1 β€” this measures an even combination of precision and recall. it is defined as 2*p*r/(p+r). in terms of a, b, and c, it may be expressed as 2a/(2a+b+c). it falls in the range from 0 to 1, with 1 being the best score. the moment. the icon. πŸ”₯

the F1 measure is often the only simple measure that is worth trying to maximize on its own β€” consider the fact that you can get a perfect precision score by always assigning zero categories, or a perfect recall score by always assigning every category. a truly smart system will assign the correct categories and only the correct categories, maximizing precision and recall at the same time, and therefore maximizing the F1 score. that's main character energy, genuinely.

sometimes it's worth trying to maximize the accuracy score, but accuracy (and its counterpart error) are considered fairly crude scores that don't give much information about the performance of a categorizer. like sure, it's a vibe, but it's not the whole story. πŸ™ˆ


πŸ’… METHODS πŸ’…

the general execution flow when using this class is to create a Statistics::Contingency object, add a bunch of results to it, and then report on the results. three steps, that's it, you got this bestie.

  • $e = Statistics::Contingency->new() β€” returns a new Statistics::Contingency object. expects a categories parameter specifying the entire set of categories that may be assigned during this experiment. also accepts a verbose parameter β€” if true, some diagnostic status information will be displayed when certain actions are performed. yes, it will tell you what it's doing. it's communicative. we love that in an object. 🫢
  • $e->add_result($assigned_categories, $correct_categories, $name) β€” adds a new result to the experiment. the lists of assigned and correct categories can be given as an array of category names (strings), as a hash whose keys are the category names and whose values are anything logically true, or as a single string if there is only one category. three formats, pick your fighter. ✨

if you've already got the lists in hash form, this will be the fastest way to pass them. otherwise, the current implementation will convert them to hash form internally in order to make its calculations efficient.

the $name parameter is an optional name for this result. it will only be used in error messages or debugging/progress output.

in the current implementation, we only store the contingency tables per category, as well as a table for the entire result set. this means that you can't recover information about any particular single result from the Statistics::Contingency object. so don't go looking, it's not there. πŸ’€

  • $e->set_entries($a, $b, $c, $d) β€” if you don't wish to use the add_result() interface, but still take advantage of the calculation methods and the various edge cases they handle, you can directly set the four elements of the contingency table with this method. for the girlies who like to do it manually. πŸ’…
  • $e->micro_accuracy β€” returns the micro-averaged accuracy for the data set.
  • $e->micro_error β€” returns the micro-averaged error for the data set.
  • $e->micro_precision β€” returns the micro-averaged precision for the data set.
  • $e->micro_recall β€” returns the micro-averaged recall for the data set.
  • $e->micro_F1 β€” returns the micro-averaged F1 for the data set.
  • $e->macro_accuracy β€” returns the macro-averaged accuracy for the data set.
  • $e->macro_error β€” returns the macro-averaged error for the data set.
  • $e->macro_precision β€” returns the macro-averaged precision for the data set.
  • $e->macro_recall β€” returns the macro-averaged recall for the data set.
  • $e->macro_F1 β€” returns the macro-averaged F1 for the data set.
  • $e->stats_table β€” returns a string combining several statistics in one graphic table. since accuracy is 1 minus error, we only report error since it takes less space to print. an optional argument specifies the number of significant digits to show in the data β€” the default is 3 significant digits. pretty table, minimal effort, obsessed. 🌈
  • $e->category_stats β€” returns a hash reference whose keys are the names of each category, and whose values contain the various statistical measures (accuracy, error, precision, recall, or F1) about each category as a hash reference. for example, to print a single statistic:
print $e->category_stats->{sports}{recall}, "\n";

or to print certain statistics for all categtories:

my $stats = $e->category_stats;
while (my ($cat, $value) = each %$stats) {
  print "Category '$cat': \n";
  print "  Accuracy: $value->{accuracy}\n";
  print "  Precision: $value->{precision}\n";
  print "  F1: $value->{F1}\n";
}

(and yes, "categtories" is right there in the original and we are respecting it, it's part of the lore now πŸŽ€)


πŸ‘‘ AUTHOR πŸ‘‘

Ken Williams <kwilliams@cpan.org> β€” the legend behind all of this. give them their flowers. πŸ’


Copyright 2002-2008 Ken Williams. All rights reserved.

this distribution is free software; you can redistribute it and/or modify it under the same terms as Perl itself. so go off, but respectfully. 🫢


and that's the whole page, bestie!! this one shipped as User Contributed Perl Documentation for perl v5.36.0, dated 2022-12-13 β€” so yeah, it's been serving these contingency table looks for a minute. go calculate something and maximize that F1. slay. πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from