annotate testdata/scripts/evaluate_lab.yeti @ 325:4cf4313d7e30 livemode

Always use q=0.8 and accept the hit on speed -- the templates are made for that configuration and it does work better. Also some adjustments to thresholding and peak picking for live mode in particular.
author Chris Cannam
date Mon, 18 May 2015 13:58:27 +0100
parents 7cb021e40732
children
rev   line source
Chris@138 1
Chris@138 2 // Take two lab files of the form
Chris@138 3 //
Chris@138 4 // onset offset frequency
Chris@138 5 //
Chris@138 6 // and report their onset-only note-level accuracy F-measure.
Chris@138 7
Chris@138 8 program evaluate_lab;
Chris@138 9
Chris@138 10 usage () =
Chris@138 11 (eprintln "\nUsage: evaluate_lab reqd reference.lab transcribed.lab\n";
Chris@138 12 eprintln "where reqd is the number of milliseconds allowed for timing error (+/-)\n");
Chris@138 13
Chris@138 14 toMIDIPitch f =
Chris@138 15 round (12 * (Math#log(f / 220) / Math#log(2)) + 57);
Chris@138 16
Chris@138 17 suck f =
Chris@138 18 (str = openInFile f "UTF-8"; // better to use readFile here, oh well
Chris@138 19 d = map do line:
Chris@138 20 case list (strSplit "\t" line) of
Chris@138 21 onset::offset::frequency::_:
Chris@138 22 { onset = number onset, midi = toMIDIPitch (number frequency) };
Chris@138 23 _:
Chris@138 24 failWith "badly formed line: \(line)";
Chris@138 25 esac;
Chris@138 26 done (str.lines ());
Chris@138 27 str.close ();
Chris@138 28 d);
Chris@138 29
Chris@138 30 select f = fold do r x: if f x then x::r else r fi done [];
Chris@138 31
Chris@138 32 evaluate permitted ref trans =
Chris@138 33 (reference = suck ref;
Chris@138 34 transcribed = suck trans;
Chris@138 35 accurate =
Chris@138 36 select do here :
Chris@138 37 any do other:
Chris@138 38 here.midi == other.midi and
Chris@138 39 abs (here.onset - other.onset) < permitted
Chris@138 40 done reference
Chris@138 41 done transcribed;
Chris@138 42 {
Chris@138 43 ntot = length transcribed,
Chris@138 44 nref = length reference,
Chris@138 45 ncorr = length accurate,
Chris@138 46 });
Chris@138 47
Chris@138 48 pc n =
Chris@138 49 int (n * 1000) / 10;
Chris@138 50
Chris@138 51 report { ntot, nref, ncorr } =
Chris@138 52 (nfp = ntot - ncorr;
Chris@138 53 nfn = nref - ncorr;
Chris@222 54 if nref == 0 then
Chris@222 55 println "ERROR: no events in reference!"
Chris@222 56 elif ntot == 0 then
Chris@222 57 println "WARNING: no events transcribed!"
Chris@222 58 else
Chris@222 59 rec = ncorr / nref;
Chris@222 60 pre = ncorr / ntot;
Chris@222 61 f = if pre + rec == 0 then 0 else 2 * ((pre * rec) / (pre + rec)) fi;
Chris@222 62 acc = ncorr / (ncorr + nfp + nfn);
Chris@222 63 println "precision \(pc pre), recall \(pc rec), accuracy \(pc acc), F \(pc f)";
Chris@222 64 fi);
Chris@138 65
Chris@138 66 case (list _argv) of
Chris@138 67 reqd::ref::trans::[]: report (evaluate (number reqd / 1000) ref trans);
Chris@138 68 _: usage ();
Chris@138 69 esac;
Chris@138 70