UMAP: removed batchSize, added fit and transform method and examples

nix
Pierre Alexandre Tremblay 5 years ago
parent eb020dd391
commit 886a3006bf

@ -1,15 +1,14 @@
FluidUMAP : FluidModelObject { 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| *new {|server,numDimensions = 2, numNeighbours = 15, minDist = 0.1, iterations = 200, learnRate = 0.1|
^super.new(server,[numDimensions, numNeighbours, minDist, iterations, learnRate, batchSize]) ^super.new(server,[numDimensions, numNeighbours, minDist, iterations, learnRate])
.numDimensions_(numDimensions) .numDimensions_(numDimensions)
.numNeighbours_(numNeighbours) .numNeighbours_(numNeighbours)
.minDist_(minDist) .minDist_(minDist)
.iterations_(iterations) .iterations_(iterations)
.learnRate_(learnRate) .learnRate_(learnRate);
.batchSize_(batchSize);
} }
prGetParams{ prGetParams{
@ -18,8 +17,7 @@ FluidUMAP : FluidModelObject {
this.numNeighbours, this.numNeighbours,
this.minDist, this.minDist,
this.iterations, this.iterations,
this.learnRate, this.learnRate
this.batchSize
] ]
} }
@ -32,6 +30,24 @@ FluidUMAP : FluidModelObject {
this.prSendMsg(this.fitTransformMsg(sourceDataSet,destDataSet)); 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 // not implemented
cols {|action|} cols {|action|}
read{|filename,action|} read{|filename,action|}

@ -1,7 +1,7 @@
TITLE:: FluidUMAP TITLE:: FluidUMAP
summary:: Dimensionality Reduction with Uniform Manifold Approximation and Projection summary:: Dimensionality Reduction with Uniform Manifold Approximation and Projection
categories:: Dimensionality Reduction, Data Processing categories:: Dimensionality Reduction, Data Processing
related:: Classes/FluidMDS, Classes/FluidDataSet related:: Classes/FluidMDS, Classes/FluidPCA, Classes/FluidDataSet
DESCRIPTION:: DESCRIPTION::
@ -53,7 +53,7 @@ code::
~normalized = FluidDataSet(s); ~normalized = FluidDataSet(s);
~standardizer = FluidStandardize(s); ~standardizer = FluidStandardize(s);
~normalizer = FluidNormalize(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 //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 = { w.drawFunc = {
Pen.use { Pen.use {
~normalizedDict.keysValuesDo{|key, val| ~normalizedDict.keysValuesDo{|key, val|
Pen.fillColor = Color.new(~colours[key.asSymbol][0], ~colours[key.asSymbol][1],~colours[key.asSymbol][2]); 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)); Pen.fillOval(Rect((val[0] * 200), (val[1] * 200), 5, 5));
~colours[key.asSymbol].flat.postln; ~colours[key.asSymbol].flat;
} }
} }
}; };
w.refresh; w.refresh;
w.front; w.front;
@ -95,5 +95,75 @@ w.front;
//play with parameters //play with parameters
~umap.numNeighbours = 10; ~umap.numNeighbours = 10;
~umap.minDist =5; ~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?
:: ::

Loading…
Cancel
Save