annotate yeti/em_onecolumn.yeti @ 19:f1f8c84339d0

Starting to revisit this EM logic and test in a single-column world
author Chris Cannam
date Wed, 26 Mar 2014 18:49:12 +0000
parents
children 982aa1197a7e
rev   line source
Chris@19 1
Chris@19 2 module em_onecolumn;
Chris@19 3
Chris@19 4 mm = load may.mathmisc;
Chris@19 5 vec = load may.vector;
Chris@19 6 mat = load may.matrix;
Chris@19 7
Chris@19 8 inRange ranges instrument note =
Chris@19 9 note >= ranges[instrument].lowest and note <= ranges[instrument].highest;
Chris@19 10
Chris@19 11 initialise ranges templates notes =
Chris@19 12 (instruments = keys ranges;
Chris@19 13 {
Chris@19 14 pitches = // z in the original. 1 per note
Chris@19 15 vec.randoms notes,
Chris@19 16 sources = // u in the original. 1 per note-instrument
Chris@19 17 mapIntoHash id
Chris@19 18 do instrument:
Chris@19 19 vec.fromList
Chris@19 20 (map do note:
Chris@19 21 if inRange ranges instrument note then 1 else 0 fi
Chris@19 22 done [0..notes-1])
Chris@19 23 done instruments,
Chris@19 24 instruments,
Chris@19 25 templates,
Chris@19 26 ranges,
Chris@19 27 lowest = head
Chris@19 28 (sort (map do i: ranges[i].lowest done instruments)),
Chris@19 29 highest = head (reverse
Chris@19 30 (sort (map do i: ranges[i].highest done instruments))),
Chris@19 31 });
Chris@19 32
Chris@19 33 epsilon = 1e-16;
Chris@19 34
Chris@19 35 select predicate = concatMap do v: if predicate v then [v] else [] fi done;
Chris@19 36
Chris@19 37 distributionsFor data instrument note =
Chris@19 38 {
Chris@19 39 w = mat.getColumn note data.templates[instrument],
Chris@19 40 p = vec.at data.pitches note,
Chris@19 41 s = vec.at data.sources[instrument] note,
Chris@19 42 };
Chris@19 43
Chris@19 44 performExpectation data column =
Chris@19 45 (estimate =
Chris@19 46 fold do acc instrument:
Chris@19 47 fold do acc note:
Chris@19 48 { w, p, s } = distributionsFor data instrument note;
Chris@19 49 vec.add [acc, vec.scaled (p * s) w];
Chris@19 50 done acc [data.ranges[instrument].lowest ..
Chris@19 51 data.ranges[instrument].highest]
Chris@19 52 done (vec.consts epsilon (vec.length column)) data.instruments;
Chris@19 53 vec.divide column estimate);
Chris@19 54
Chris@19 55 performMaximisation data column q =
Chris@19 56 (pitchTop = vec.fromList
Chris@19 57 (map do note:
Chris@19 58 fold do acc instrument:
Chris@19 59 { w, p, s } = distributionsFor data instrument note;
Chris@19 60 fold do acc bin:
Chris@19 61 acc + s * (vec.at w bin) * (vec.at column bin);
Chris@19 62 done acc [0..vec.length column - 1]
Chris@19 63 done epsilon data.instruments;
Chris@19 64 done [data.lowest .. data.highest]);
Chris@19 65 pitchBottom = vec.sum pitchTop;
Chris@19 66
Chris@19 67 /* sourceTop = vec.fromList
Chris@19 68 (map do instrument:
Chris@19 69 fold do acc note:
Chris@19 70 { w, p, s } = distributionsFor data instrument note;
Chris@19 71 fold do acc bin:
Chris@19 72 acc + p * (vec.at w bin) * (vec.at column bin);
Chris@19 73 done acc [0..vec.length column - 1]
Chris@19 74 done epsilon [data.lowest .. data.highest]
Chris@19 75 done data.instruments);
Chris@19 76 sourceBottom = vec.sum sourceTop;
Chris@19 77 */
Chris@19 78 data with {
Chris@19 79 pitches = vec.divideBy pitchBottom pitchTop,
Chris@19 80 // sources = vec.divideBy sourceBottom sourceTop
Chris@19 81 });
Chris@19 82
Chris@19 83 {
Chris@19 84 initialise,
Chris@19 85 performExpectation,
Chris@19 86 performMaximisation,
Chris@19 87 }
Chris@19 88
Chris@19 89