diff --git a/release-packaging/Classes/FluidUMAP.sc b/release-packaging/Classes/FluidUMAP.sc index 9083a3f..00c459e 100644 --- a/release-packaging/Classes/FluidUMAP.sc +++ b/release-packaging/Classes/FluidUMAP.sc @@ -1,15 +1,14 @@ FluidUMAP : FluidModelObject { - var <>numDimensions, <>numNeighbours, <>minDist, <>iterations, <>learnRate, <>batchSize; + var <>numDimensions, <>numNeighbours, <>minDist, <>iterations, <>learnRate; - *new {|server,numDimensions = 2, numNeighbours = 15, minDist = 0.1, iterations = 200, learnRate = 0.1, batchSize = 50| - ^super.new(server,[numDimensions, numNeighbours, minDist, iterations, learnRate, batchSize]) + *new {|server,numDimensions = 2, numNeighbours = 15, minDist = 0.1, iterations = 200, learnRate = 0.1| + ^super.new(server,[numDimensions, numNeighbours, minDist, iterations, learnRate]) .numDimensions_(numDimensions) .numNeighbours_(numNeighbours) .minDist_(minDist) .iterations_(iterations) - .learnRate_(learnRate) - .batchSize_(batchSize); + .learnRate_(learnRate); } prGetParams{ @@ -18,8 +17,7 @@ FluidUMAP : FluidModelObject { this.numNeighbours, this.minDist, this.iterations, - this.learnRate, - this.batchSize + this.learnRate ] } @@ -32,6 +30,24 @@ FluidUMAP : FluidModelObject { this.prSendMsg(this.fitTransformMsg(sourceDataSet,destDataSet)); } + fitMsg{|dataSet| + ^this.prMakeMsg(\fit,id, dataSet.id); + } + + fit{|dataSet, action| + actions[\fit] = [nil, action]; + this.prSendMsg(this.fitMsg(dataSet)); + } + + transformMsg{|sourceDataSet, destDataSet| + ^this.prMakeMsg(\transform, id, sourceDataSet.id, destDataSet.id); + } + + transform{|sourceDataSet, destDataSet, action| + actions[\transform] = [nil, action]; + this.prSendMsg(this.transformMsg(sourceDataSet,destDataSet)); + } + // not implemented cols {|action|} read{|filename,action|} diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index 381dea1..16d27a2 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -1,7 +1,7 @@ TITLE:: FluidUMAP summary:: Dimensionality Reduction with Uniform Manifold Approximation and Projection categories:: Dimensionality Reduction, Data Processing -related:: Classes/FluidMDS, Classes/FluidDataSet +related:: Classes/FluidMDS, Classes/FluidPCA, Classes/FluidDataSet DESCRIPTION:: @@ -53,7 +53,7 @@ code:: ~normalized = FluidDataSet(s); ~standardizer = FluidStandardize(s); ~normalizer = FluidNormalize(s); -~umap = FluidUMAP(s).numDimensions_(2).numNeighbours_(5).minDist_(0.2).iterations_(50). learnRate_(0.2).batchSize_(50); +~umap = FluidUMAP(s).numDimensions_(2).numNeighbours_(5).minDist_(0.2).iterations_(50).learnRate_(0.2); ) @@ -78,15 +78,15 @@ code:: //Visualise the 2D projection of our original 4D data ( -w = Window("scatter", Rect(128, 64, 200, 200)); +w = Window("a perspective", Rect(128, 64, 200, 200)); w.drawFunc = { - Pen.use { - ~normalizedDict.keysValuesDo{|key, val| + Pen.use { + ~normalizedDict.keysValuesDo{|key, val| Pen.fillColor = Color.new(~colours[key.asSymbol][0], ~colours[key.asSymbol][1],~colours[key.asSymbol][2]); Pen.fillOval(Rect((val[0] * 200), (val[1] * 200), 5, 5)); - ~colours[key.asSymbol].flat.postln; - } - } + ~colours[key.asSymbol].flat; + } + } }; w.refresh; w.front; @@ -95,5 +95,75 @@ w.front; //play with parameters ~umap.numNeighbours = 10; ~umap.minDist =5; -~umap.batchSize = 10; + +//rerun the UMAP +~umap.fitTransform(~standardized,~reduced,action:{"Finished UMAP".postln}); + +//draw to compare +( +~normalizer.fitTransform(~reduced,~normalized,action:{ + "Normalized Output".postln; + ~normalized.dump{|x| + ~normalizedDict = x["data"]; + + { + w = Window("another perspective", Rect(328, 64, 200, 200)); + w.drawFunc = { + Pen.use { + ~normalizedDict.keysValuesDo{|key, val| + Pen.fillColor = Color.new(~colours[key.asSymbol][0], ~colours[key.asSymbol][1],~colours[key.asSymbol][2]); + Pen.fillOval(Rect((val[0] * 200), (val[1] * 200), 5, 5)); + ~colours[key.asSymbol].flat; + }; + }; + }; + w.refresh; + w.front; + + }.defer; + + }; +}); +) + +// now run new random points on the same training material. Colours should be scattered around the same space (BUT THEY DON'T RIGHT NOW) + +~newDS = FluidDataSet(s); +~colours2 = Dictionary.newFrom(400.collect{|i|[("entry"++i).asSymbol, 3.collect{1.0.rand}]}.flatten(1)); +~newDS.load(Dictionary.newFrom([\cols, 3, \data, ~colours2])); + +//we need to standardize to the same space +~newDSstan = FluidDataSet(s); +~standardizer.transform(~newDS, ~newDSstan); + +//then we can run the umap +~newDSmap = FluidDataSet(s); +~umap.transform(~newDSstan, ~newDSmap); + +//then we can draw and look +( +~normalizer.transform(~newDSmap,~normalized,action:{ + "Normalized Output".postln; + ~normalized.dump{|x| + ~normalizedDict = x["data"]; + { + w = Window("new material", Rect(528, 64, 200, 200)); + w.drawFunc = { + Pen.use { + ~normalizedDict.keysValuesDo{|key, val| + Pen.fillColor = Color.new(~colours2[key.asSymbol][0], ~colours2[key.asSymbol][1],~colours2[key.asSymbol][2]); + Pen.fillOval(Rect((val[0] * 200), (val[1] * 200), 5, 5)); + ~colours2[key.asSymbol].flat; + }; + }; + }; + w.refresh; + w.front; + }.defer; + }; +}); +) + +//same process as above in 2 passes maybe? + ::