From 81110de196e1cc154e7a3d07d2b130d9341a2bf3 Mon Sep 17 00:00:00 2001 From: Gerard Roma Date: Tue, 14 Jun 2022 10:05:32 +0100 Subject: [PATCH] Feature/skmeans (#66) * add PCA whitening parameter * add FluidSKMeans * SKMeans correction * added RT query * transform -> encode * added to overview Co-authored-by: Gerard Co-authored-by: tremblap --- release-packaging/Classes/FluidSKMeans.sc | 136 ++++++++++++++++++ .../Guides/FluidCorpusManipulation.schelp | 1 + scripts/settings/FluidManipulation.cpp.in | 1 + 3 files changed, 138 insertions(+) create mode 100644 release-packaging/Classes/FluidSKMeans.sc diff --git a/release-packaging/Classes/FluidSKMeans.sc b/release-packaging/Classes/FluidSKMeans.sc new file mode 100644 index 0000000..f53d450 --- /dev/null +++ b/release-packaging/Classes/FluidSKMeans.sc @@ -0,0 +1,136 @@ +FluidSKMeans : FluidModelObject { + + var clusters, threshold, maxiter; + + *new {|server, numClusters = 4, encodingThreshold = 0.25, maxIter = 100| + ^super.new(server,[numClusters,maxIter, encodingThreshold]) + .numClusters_(numClusters) + .encodingThreshold_(encodingThreshold) + .maxIter_(maxIter); + } + + numClusters_{|n| clusters = n.asInteger} + numClusters{ ^clusters } + + encodingThreshold_{|t| threshold = t.asFloat} + encodingThreshold{ ^threshold } + + maxIter_{|i| maxiter = i.asInteger} + maxIter{ ^maxiter } + + + prGetParams{^[this.id,this.numClusters, this.encodingThreshold, this.maxIter];} + + fitMsg{ |dataSet| ^this.prMakeMsg(\fit,id,dataSet.id);} + + fit{|dataSet, action| + actions[\fit] = [ + numbers( FluidMessageResponse, _, this.numClusters ,_), + action + ]; + this.prSendMsg(this.fitMsg(dataSet)); + } + + fitPredictMsg{|dataSet, labelSet| + ^this.prMakeMsg(\fitPredict, id, dataSet.id, labelSet.id) + } + + fitPredict{|dataSet, labelSet,action| + actions[\fitPredict] = [ + numbers(FluidMessageResponse, _, this.numClusters, _), + action + ]; + this.prSendMsg(this.fitPredictMsg(dataSet,labelSet)); + } + + predictMsg{|dataSet, labelSet| + ^this.prMakeMsg(\predict, id, dataSet.id, labelSet.id) + } + + predict{ |dataSet, labelSet, action| + actions[\predict] = [ + numbers(FluidMessageResponse, _, this.numClusters, _), + action + ]; + this.prSendMsg(this.predictMsg(dataSet,labelSet)); + } + + predictPointMsg{|buffer| + ^this.prMakeMsg(\predictPoint, id, this.prEncodeBuffer(buffer)) + } + + predictPoint { |buffer, action| + actions[\predictPoint] = [number(FluidMessageResponse,_,_),action]; + this.prSendMsg(this.predictPointMsg(buffer)) + } + + fitEncodeMsg{|srcDataSet, dstDataSet| + ^this.prMakeMsg(\fitEncode, id, srcDataSet.id, dstDataSet.id) + } + + fitEncode{|srcDataSet, dstDataSet,action| + actions[\fitEncode] = [nil,action]; + this.prSendMsg(this.fitEncodeMsg(srcDataSet,dstDataSet)); + } + + encodeMsg{|srcDataSet, dstDataSet| + ^this.prMakeMsg(\encode, id, srcDataSet.id, dstDataSet.id) + } + + encode{ |srcDataSet, dstDataSet, action| + actions[\encode] = [nil,action]; + this.prSendMsg(this.encodeMsg(srcDataSet,dstDataSet)); + } + + encodePointMsg{ |sourceBuffer, targetBuffer| + ^this.prMakeMsg(\encodePoint, id, + this.prEncodeBuffer(sourceBuffer), + this.prEncodeBuffer(targetBuffer), + ["/b_query", targetBuffer.asUGenInput]); + } + + encodePoint { |sourceBuffer, targetBuffer, action| + actions[\encodePoint] = [nil,{action.value(targetBuffer)}]; + this.prSendMsg(this.encodePointMsg(sourceBuffer, targetBuffer)); + } + + getMeansMsg{|dataSet| ^this.prMakeMsg(\getMeans, id, dataSet.asUGenInput) } + + getMeans{ |dataSet, action| + actions[\getMeans] = [nil, action]; + this.prSendMsg(this.getMeansMsg(dataSet)); + } + + setMeansMsg{|dataSet| ^this.prMakeMsg(\setMeans, id, dataSet.asUGenInput) } + + setMeans{ |dataSet, action| + actions[\setMeans] = [nil, action]; + this.prSendMsg(this.setMeansMsg(dataSet)); + } + + clearMsg{ ^this.prMakeMsg(\clear, id) } + + clear{ |action| + actions[\clear] = [nil, action]; + this.prSendMsg(this.clearMsg); + } + + kr{|trig, inputBuffer,outputBuffer| + ^FluidSKMeansQuery.kr(trig, + this, + this.prEncodeBuffer(inputBuffer), + this.prEncodeBuffer(outputBuffer)); + } +} + +FluidSKMeansQuery : FluidRTMultiOutUGen { + + *kr{ |trig, model,inputBuffer, outputBuffer | + ^this.multiNew('control',trig, model.asUGenInput,inputBuffer.asUGenInput, outputBuffer.asUGenInput) + } + + init { arg ... theInputs; + inputs = theInputs; + ^this.initOutputs(1, rate); + } +} diff --git a/release-packaging/HelpSource/Guides/FluidCorpusManipulation.schelp b/release-packaging/HelpSource/Guides/FluidCorpusManipulation.schelp index aace807..92e2e29 100644 --- a/release-packaging/HelpSource/Guides/FluidCorpusManipulation.schelp +++ b/release-packaging/HelpSource/Guides/FluidCorpusManipulation.schelp @@ -99,6 +99,7 @@ table:: ##link::Classes/FluidPCA:: || Principal Component Analysis for preprocessing and dimension reduction ##link::Classes/FluidMDS:: || Multidimensional Scaling for dimension reduction ##link::Classes/FluidKMeans:: || K-Means clustering +##link::Classes/FluidSKMeans:: || Spherical K-Means clustering ##link::Classes/FluidUMAP:: || Dimension reduction with UMAP algorithm ##link::Classes/FluidGrid:: || Transform a data set of two dimensional points into a two dimensional grid using the Munkres Algorithm. :: diff --git a/scripts/settings/FluidManipulation.cpp.in b/scripts/settings/FluidManipulation.cpp.in index f2d72cb..f835956 100644 --- a/scripts/settings/FluidManipulation.cpp.in +++ b/scripts/settings/FluidManipulation.cpp.in @@ -1,5 +1,6 @@ makeSCWrapper("FluidKDTreeQuery",inTable); makeSCWrapper("FluidKMeansQuery",inTable); + makeSCWrapper("FluidSKMeansQuery",inTable); makeSCWrapper("FluidKNNClassifierQuery",inTable); makeSCWrapper("FluidKNNRegressorQuery",inTable); makeSCWrapper("FluidNormalizeQuery",inTable);