From 31d8150946ce84d6a8e868337ec97b35e1f78f9c Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Sun, 19 Jul 2020 11:26:42 +0100 Subject: [PATCH] more verbose KDTree KR example and AE example --- .../Examples/dataset/MLP-AE-dataredux.scd | 78 +++++++++++++++++++ .../HelpSource/Classes/FluidKDTree.schelp | 18 ++++- 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 release-packaging/Examples/dataset/MLP-AE-dataredux.scd diff --git a/release-packaging/Examples/dataset/MLP-AE-dataredux.scd b/release-packaging/Examples/dataset/MLP-AE-dataredux.scd new file mode 100644 index 0000000..dc2d937 --- /dev/null +++ b/release-packaging/Examples/dataset/MLP-AE-dataredux.scd @@ -0,0 +1,78 @@ +s.reboot; +//Preliminaries: we want some audio, a couple of FluidDataSets, some Buffers +( +~raw = FluidDataSet(s,\MLP40); +~retrieved = FluidDataSet(s,\ae2); +~audio = Buffer.read(s,File.realpath(FluidBufMelBands.class.filenameSymbol).dirname +/+ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav"); +~melfeatures = Buffer.new(s); +~stats = Buffer.alloc(s, 7, 40); +~datapoint = Buffer.alloc(s, 40); +~mlp = FluidMLPRegressor(s,[10,2,10],1,1,2,10000,0.01,0.1,10,0); +) + +// process the melbands +FluidBufMelBands.process(s,~audio, features: ~melfeatures,action: {\done.postln;}); + +~raw.free +// Divide the time series in 100, and take the mean of each segment and add this as a point to +// the 'raw' FluidDataSet +( +{ + var trig = LocalIn.kr(1, 1); + var buf = LocalBuf(40, 1); + var count = PulseCount.kr(trig) - 1; + var chunkLen = (~melfeatures.numFrames / 100).asInteger; + var stats = FluidBufStats.kr(source: ~melfeatures, startFrame: count * chunkLen, numFrames: chunkLen, stats: ~stats, trig: trig); + var rd = BufRd.kr(40, ~stats, DC.kr(0), 0, 1); + var bufWr, dsWr; + 40.do{|i| + bufWr = BufWr.kr(rd[i], buf, DC.kr(i)); + }; + dsWr = FluidDataSetWr.kr(\MLP40, buf: buf, trig: Done.kr(stats)); + LocalOut.kr( Done.kr(dsWr)); + FreeSelf.kr(count - 99); +}.play; +) +// wait for the post window to acknoledge the job is done. + +//we can then run the AE - the server might become yellow :) +~mlp.fit(~raw,~raw,{|x|x.postln;}); + +//we can then retrieve the hidden layer #2 +~mlp.predict(~raw,~retrieved) + +//check the structure of retrieved +~retrieved.print + +//let's normalise it for display +~normData = FluidDataSet(s,\ae2N); +~reducedarray = Array.new(100); +~normalizer = FluidNormalize(s); +~normalizer.fitTransform(~retrieved,~normData, action:{ + ~normData.dump{|x| 100.do{|i| + ~reducedarray.add(x["data"][i.asString]) + }}; +}); + +~normData.print +~reducedarray.postln; + + +//Visualise the 2D projection of our original 12D data +( +d = ~reducedarray.flatten(1).unlace.deepCollect(1, { |x| x.normalize}); +w = Window("scatter", Rect(128, 64, 200, 200)); +w.drawFunc = { + Pen.use { + d[0].size.do{|i| + var x = (d[0][i]*200); + var y = (d[1][i]*200); + var r = Rect(x,y,5,5); + Pen.fillColor = Color.blue; + Pen.fillOval(r); + } + } +}; +w.refresh; +w.front; +) \ No newline at end of file diff --git a/release-packaging/HelpSource/Classes/FluidKDTree.schelp b/release-packaging/HelpSource/Classes/FluidKDTree.schelp index b978d6a..c469b8b 100644 --- a/release-packaging/HelpSource/Classes/FluidKDTree.schelp +++ b/release-packaging/HelpSource/Classes/FluidKDTree.schelp @@ -53,6 +53,7 @@ s.boot; ( fork{ ~ds = FluidDataSet.new(s,\kdtree_help_rand2d); + ~dsL = FluidDataSet.new(s,\kdtree_help_indices);// for use later in KR query d = Dictionary.with( *[\cols -> 2,\data -> Dictionary.newFrom( 100.collect{|i| [i, [ 1.0.linrand,1.0.linrand]]}.flatten)]); @@ -62,7 +63,7 @@ fork{ ) // Make a new tree, and fit it to the DataSet -~tree = FluidKDTree(s,numNeighbours:5,lookupDataSet:~ds); +~tree = FluidKDTree(s,numNeighbours:5,lookupDataSet:~dsL); //Fit it to the DataSet ~tree.fit(~ds); @@ -101,13 +102,26 @@ subsection:: Server Side Queries code:: +//set the buffers and busses needed ( ~inputPoint = Buffer.alloc(s,2); -~predictPoint = Buffer.alloc(s,10); +~predictPoint = Buffer.alloc(s,5); ~pitchingBus = Bus.control; ~catchingBus = Bus.control; ) +//populate the lookupDataSet +//here we populate with numbers that are in effect the indicies, but it could be anything numerical that will be returned on the server-side and would be usable on that side +( +fork{ + d = Dictionary.with( + *[\cols -> 1,\data -> Dictionary.newFrom( + 100.collect{|i| [i, [ i ]]}.flatten)]); + s.sync; + ~dsL.load(d, {~dsL.print}); +} +) + ( ~tree.inBus_(~pitchingBus).outBus_(~catchingBus).inBuffer_(~inputPoint).outBuffer_(~predictPoint);