Mercurial > hg > silvet
changeset 22:782b910394f3
Instruments by number rather than by name
author | Chris Cannam |
---|---|
date | Fri, 28 Mar 2014 14:00:40 +0000 |
parents | 8e61ec97b34e |
children | 990b8b8b7e25 |
files | yeti/em_onecolumn.yeti yeti/silvet.yeti yeti/templates.yeti |
diffstat | 3 files changed, 63 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/yeti/em_onecolumn.yeti Fri Mar 28 12:52:11 2014 +0000 +++ b/yeti/em_onecolumn.yeti Fri Mar 28 14:00:40 2014 +0000 @@ -10,82 +10,100 @@ inRange ranges instrument note = note >= ranges[instrument].lowest and note <= ranges[instrument].highest; +normalise v = + (s = vec.sum v; + if s > 0 then vec.divideBy s v + else v + fi); + initialise ranges templates notes = - (instruments = keys ranges; + (instruments = sort (keys ranges); { pitches = // z in the original. 1 per note - vec.randoms notes, + normalise (vec.randoms notes), sources = // u in the original. 1 per note-instrument - mapIntoHash id - do instrument: + //!!! should this be normalised across instruments? i.e. row-wise + mat.fromColumns + (map 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, + done instruments), + instruments = array instruments, + instCount = length instruments, + templates = array + (map do iname: + m = templates[iname]; + mat.fromColumns (map normalise (mat.asColumns m)) + done instruments), + ranges = array + (map do iname: + ranges[iname] + done instruments), lowest = head - (sort (map do i: ranges[i].lowest done instruments)), + (sort (map do iname: ranges[iname].lowest done instruments)), highest = head (reverse - (sort (map do i: ranges[i].highest done instruments))), + (sort (map do iname: ranges[iname].highest done instruments))), }); epsilon = 1e-16; select predicate = concatMap do v: if predicate v then [v] else [] fi done; -distributionsFor data instrument note = +distributionsFor data instNo note = { - w = mat.getColumn note data.templates[instrument], + w = mat.getColumn note data.templates[instNo], p = vec.at data.pitches note, - s = vec.at data.sources[instrument] note, + s = mat.at data.sources note instNo, }; performExpectation data column = - (estimate = - fold do acc instrument: + (column = normalise column; + estimate = + fold do acc inst: fold do acc note: - { w, p, s } = distributionsFor data instrument note; + { w, p, s } = distributionsFor data inst 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; + done acc [data.ranges[inst].lowest .. + data.ranges[inst].highest] + done (vec.consts epsilon (vec.length column)) [0..data.instCount-1]; vec.divide column estimate); performMaximisation data column q = - (pitches = vec.fromList + (column = normalise column; + + pitches = vec.fromList (map do note: - fold do acc instrument: - { w, p, s } = distributionsFor data instrument note; + fold do acc inst: + { w, p, s } = distributionsFor data inst note; fold do acc bin: acc + s * p * (vec.at w bin) * (vec.at q bin); done acc [0..vec.length column - 1] - done epsilon data.instruments; + done epsilon [0..data.instCount-1]; done [data.lowest .. data.highest]); pitches = vec.divideBy (vec.sum pitches) pitches; - sources = mapIntoHash id - do instrument: vec.fromList + sources = mat.fromColumns + (map do inst: vec.fromList (map do note: - if not inRange data.ranges instrument note then epsilon else - { w, p, s } = distributionsFor data instrument note; + if not inRange data.ranges inst note then epsilon else + { w, p, s } = distributionsFor data inst note; fold do acc bin: acc + s * p * (vec.at w bin) * (vec.at q bin); done epsilon [0..vec.length column - 1] fi; done [data.lowest .. data.highest]) - done data.instruments; + done [0..data.instCount-1]); - sourceDenoms = fold do acc instrument: - vec.add [acc, sources[instrument]] - done (vec.zeros (data.highest - data.lowest + 1)) data.instruments; + sourceDenoms = fold do acc inst: + vec.add [acc, (mat.getColumn inst sources)] + done (vec.zeros (data.highest - data.lowest + 1)) [0..data.instCount-1]; - sources = mapIntoHash id - do instrument: - vec.divide sources[instrument] sourceDenoms; - done (keys sources); + sources = mat.fromColumns + (map do inst: + vec.divide (mat.getColumn inst sources) sourceDenoms; + done [0..data.instCount-1]); data with { pitches,
--- a/yeti/silvet.yeti Fri Mar 28 12:52:11 2014 +0000 +++ b/yeti/silvet.yeti Fri Mar 28 14:00:40 2014 +0000 @@ -68,10 +68,7 @@ \() (plot.plot [ Caption "Source frequency distribution", Vector col ]); -sourceGrid d = - mat.fromColumns (map do k: d.sources[k] done (sort (keys d.sources))); - -\() (plot.plot [ Caption "Source distribution beforehand", Grid (sourceGrid em1data)]); +\() (plot.plot [ Caption "Source distribution beforehand", Grid em1data.sources]); oneIteration em1data col n = (q = em1.performExpectation em1data col; @@ -79,7 +76,7 @@ newdata = em1.performMaximisation em1data col q; if (n % 6 == 0) then \() (plot.plot [ Caption "Pitch distribution before and after M-step update for iteration \(n)", Vector (em1data.pitches), Vector (newdata.pitches) ]); - \() (plot.plot [ Caption "Source distribution after M-step update for iteration \(n)", Grid (sourceGrid newdata) ]); + \() (plot.plot [ Caption "Source distribution after M-step update for iteration \(n)", Grid newdata.sources ]); fi; newdata); @@ -93,7 +90,7 @@ var sounding = []; -println "pitch distribution: \(d.pitches)"; +println "pitch distribution: \(vec.list d.pitches)"; for [d.lowest .. d.highest] do p: if (vec.at d.pitches p) > 0.05 then @@ -109,22 +106,22 @@ var instruments = []; for sounding do p: - var best = ""; + var best = 0; var bestp = 0; - for d.instruments do i: - if vec.at d.sources[i] p > bestp then - bestp := vec.at d.sources[i] p; + for [0..d.instCount-1] do i: + if mat.at d.sources p i > bestp then + bestp := mat.at d.sources p i; best := i; fi; done; if bestp > 0 then instruments := instruments ++ [best]; else - instruments := instruments ++ ["unknown"]; + instruments := instruments ++ [-1]; fi; done; -println "Instruments: \(instruments)"; +println "Instruments: \(map do i: (d.instruments[i]) done instruments)"; ();
--- a/yeti/templates.yeti Fri Mar 28 12:52:11 2014 +0000 +++ b/yeti/templates.yeti Fri Mar 28 14:00:40 2014 +0000 @@ -30,7 +30,7 @@ done; done instruments; -//!!! these ranges are hardcoded in the original (and are a bit more restrictive) +//!!! these ranges are hardcoded, in the original (and are a bit more restrictive) extractRanges templates = mapIntoHash id do instrument: levels = map vec.sum (mat.asColumns (templates[instrument]));