TITLE:: FluidKNNRegressor summary:: Regression with K Nearest Neighbours categories:: Regression related:: Classes/FluidKNNClassifier, Classes/FluidDataSet DESCRIPTION:: A nearest-neighbor regressor. A continuous value is predicted for each point as the (weighted) average value of its nearest neighbors. 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; :: subsection:: Server Side Queries code:: //Setup ( ~inputPoint = Buffer.alloc(s,1); ~predictPoint = Buffer.alloc(s,2); ~avgBuf = Buffer.alloc(s,10,2); ~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 ) ::