You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.5 KiB
Plaintext
145 lines
3.5 KiB
Plaintext
TITLE:: FluidKNNRegressor
|
|
summary:: Regression with K Nearest Neighbours
|
|
categories:: Regression
|
|
related:: Classes/FluidKNNClassifier, Classes/FluidDataSet
|
|
|
|
DESCRIPTION::
|
|
A nearest-neighbour regressor. A continuous value is predicted for each point as the (weighted) average value of its nearest neighbours.
|
|
|
|
https://scikit-learn.org/stable/modules/neighbors.html#regression
|
|
|
|
CLASSMETHODS::
|
|
|
|
METHOD:: new
|
|
Create a new KNN regressor on the server
|
|
ARGUMENT:: server
|
|
The server to run this model on.
|
|
ARGUMENT:: numNeighbours
|
|
number of neigbours to consider in mapping, min 1
|
|
ARGUMENT:: weight
|
|
Whether to weight neighbours by distance when producing new point
|
|
|
|
INSTANCEMETHODS::
|
|
|
|
METHOD:: fit
|
|
Map a source link::Classes/FluidDataSet:: to a one-dimensional target; both DataSets need to have the same number of points.
|
|
ARGUMENT:: sourceDataSet
|
|
Source data
|
|
ARGUMENT:: targetDataSet
|
|
Target data
|
|
ARGUMENT:: action
|
|
Run when done
|
|
|
|
|
|
METHOD:: predict
|
|
Apply learned mapping to a link::Classes/FluidDataSet:: and write to an output DataSet
|
|
ARGUMENT:: sourceDataSet
|
|
data to regress
|
|
ARGUMENT:: targetDataSet
|
|
output data
|
|
ARGUMENT:: action
|
|
Run when done
|
|
|
|
METHOD:: predictPoint
|
|
Apply learned mapping to a data point in a link::Classes/Buffer::
|
|
ARGUMENT:: buffer
|
|
data point
|
|
ARGUMENT:: action
|
|
Run when done
|
|
|
|
EXAMPLES::
|
|
|
|
code::
|
|
|
|
//Make a simple mapping between a ramp and a sine cycle, test with an exponentional ramp
|
|
(
|
|
~source = FluidDataSet(s,\knn_regress_src);
|
|
~target = FluidDataSet(s,\knn_regress_tgt);
|
|
~test = FluidDataSet(s,\knn_regress_test);
|
|
~output = FluidDataSet(s,\knn_regress_out);
|
|
~tmpbuf = Buffer.alloc(s,1);
|
|
~regressor = FluidKNNRegressor(s);
|
|
)
|
|
|
|
//Make source, target and test data
|
|
(
|
|
~sourcedata = 128.collect{|i|i/128};
|
|
~targetdata = 128.collect{|i| sin(2*pi*i/128) };
|
|
~testdata = 128.collect{|i|(i/128)**2};
|
|
|
|
~source.load(
|
|
Dictionary.with(
|
|
*[\cols -> 1,\data -> Dictionary.newFrom(
|
|
~sourcedata.collect{|x, i| [i.asString, [x]]}.flatten)])
|
|
);
|
|
|
|
~target.load(
|
|
d = Dictionary.with(
|
|
*[\cols -> 1,\data -> Dictionary.newFrom(
|
|
~targetdata.collect{|x, i| [i.asString, [x]]}.flatten)]);
|
|
);
|
|
|
|
~test.load(
|
|
Dictionary.with(
|
|
*[\cols -> 1,\data -> Dictionary.newFrom(
|
|
~testdata.collect{|x, i| [i.asString, [x]]}.flatten)])
|
|
);
|
|
|
|
~targetdata.plot;
|
|
~source.print;
|
|
~target.print;
|
|
~test.print;
|
|
|
|
)
|
|
|
|
// Now make a regressor and fit it to the source and target, and predict against test
|
|
//grab the output data whilst we're at it, so we can inspect
|
|
(
|
|
~outputdata = Array(128);
|
|
~regressor.fit(~source, ~target);
|
|
~regressor.predict(~test, ~output, 1, action:{
|
|
~output.dump{|x| 128.do{|i|
|
|
~outputdata.add(x["data"][i.asString][0])
|
|
}};
|
|
});
|
|
)
|
|
|
|
//We should see a single cycle of a chirp
|
|
~outputdata.plot;
|
|
|
|
// single point transform on arbitrary value
|
|
~inbuf = Buffer.loadCollection(s,[0.5]);
|
|
~regressor.predictPoint(~inbuf,{|x|x.postln;});
|
|
::
|
|
|
|
subsection:: Server Side Queries
|
|
|
|
code::
|
|
//Setup
|
|
(
|
|
~inputPoint = Buffer.alloc(s,1);
|
|
~predictPoint = Buffer.alloc(s,1);
|
|
~pitchingBus = Bus.control;
|
|
~catchingBus = Bus.control;
|
|
)
|
|
|
|
(
|
|
~regressor.inBus_(~pitchingBus).outBus_(~catchingBus).inBuffer_(~inputPoint).outBuffer_(~predictPoint);
|
|
|
|
~inputSynth = {
|
|
var input = Saw.kr(2).linlin(-1,1,0,1);
|
|
var trig = Impulse.kr(ControlRate.ir/10);
|
|
BufWr.kr(input,~inputPoint,0);
|
|
Out.kr(~pitchingBus.index,[trig]);
|
|
};
|
|
|
|
~inputSynth.play(~regressor.synth,addAction:\addBefore);
|
|
|
|
~outputSynth = {
|
|
Poll.kr(In.kr(~catchingBus.index),BufRd.kr(1,~predictPoint,0),"mapped value")
|
|
};
|
|
~outputSynth.play(~regressor.synth,addAction:\addAfter);
|
|
~outputSynth.scope
|
|
)
|
|
::
|