Mercurial > hg > silvet
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/yeti/em_onecolumn.yeti Wed Mar 26 18:49:12 2014 +0000 @@ -0,0 +1,89 @@ + +module em_onecolumn; + +mm = load may.mathmisc; +vec = load may.vector; +mat = load may.matrix; + +inRange ranges instrument note = + note >= ranges[instrument].lowest and note <= ranges[instrument].highest; + +initialise ranges templates notes = + (instruments = keys ranges; + { + pitches = // z in the original. 1 per note + vec.randoms notes, + sources = // u in the original. 1 per note-instrument + mapIntoHash id + do instrument: + vec.fromList + (map do note: + if inRange ranges instrument note then 1 else 0 fi + done [0..notes-1]) + done instruments, + instruments, + templates, + ranges, + lowest = head + (sort (map do i: ranges[i].lowest done instruments)), + highest = head (reverse + (sort (map do i: ranges[i].highest done instruments))), + }); + +epsilon = 1e-16; + +select predicate = concatMap do v: if predicate v then [v] else [] fi done; + +distributionsFor data instrument note = + { + w = mat.getColumn note data.templates[instrument], + p = vec.at data.pitches note, + s = vec.at data.sources[instrument] note, + }; + +performExpectation data column = + (estimate = + fold do acc instrument: + fold do acc note: + { w, p, s } = distributionsFor data instrument note; + vec.add [acc, vec.scaled (p * s) w]; + done acc [data.ranges[instrument].lowest .. + data.ranges[instrument].highest] + done (vec.consts epsilon (vec.length column)) data.instruments; + vec.divide column estimate); + +performMaximisation data column q = + (pitchTop = vec.fromList + (map do note: + fold do acc instrument: + { w, p, s } = distributionsFor data instrument note; + fold do acc bin: + acc + s * (vec.at w bin) * (vec.at column bin); + done acc [0..vec.length column - 1] + done epsilon data.instruments; + done [data.lowest .. data.highest]); + pitchBottom = vec.sum pitchTop; + +/* sourceTop = vec.fromList + (map do instrument: + fold do acc note: + { w, p, s } = distributionsFor data instrument note; + fold do acc bin: + acc + p * (vec.at w bin) * (vec.at column bin); + done acc [0..vec.length column - 1] + done epsilon [data.lowest .. data.highest] + done data.instruments); + sourceBottom = vec.sum sourceTop; +*/ + data with { + pitches = vec.divideBy pitchBottom pitchTop, +// sources = vec.divideBy sourceBottom sourceTop + }); + +{ + initialise, + performExpectation, + performMaximisation, +} + +