Accord.Net Get equation of the SVM model - c#

I have been testing the sample Kernel Support Vector Machines for regression problems and I would like to know how do you get the equation of the model.
For example, if the machine is created using a polynomial kernel (degree = 1), how do you get the line equation (mx + b) of this model. Is there any method in the SupportVectorMachine Class to get the model equation? or is there any way to calculate the parameters of the equation from the variables obtained after the machine is created.
Thanks in advance.

Looks like you can use this method below:
ToWeights(), which
Converts a Linear-kernel machine into an array of linear coefficients.
The first position in the array is the Threshold value.
So in your language, the first position in the array is the bias b and the rest are your linear coefficients m.

I got weird coefficients from ToWeights() when using SequentialMinimalOptimization() from which I couldn't derive the hyperplane equation. Using LinearCoordinateDescent() yielded usable coefficients for the model, however, in the form of [a,b,c...] which could be plugged in as 0 = a + bx + cy + ...
Hope that helps!

As #zrolfs noted, if you are using Accord.NET with Sequential Minimal Optimization, the ToWeights() function does not currently return relevant coefficients for the decision function. Nevertheless, you can calculate these coefficients directly. In order to do so, multiply the SVM weights vector by the matrix of support vectors, like so:
double[] DecisionFunctionCoefficients = new double[dwTotalFeatures];
for (int iFeature = 0; iFeature < dwTotalFeatures; iFeature++) {
for (int iVector = 0; iVector < SVM.SupportVectors.Length; iVector++) {
DecisionFunctionCoefficients[iFeature] += (SVM.SupportVectors[iVector][iFeature] * SVM.Weights[iVector]);
}
}

Related

How to interpolate between multiple biome height-maps?

For biome area distribution I combine perlin noise representing temperature, and moisture levels using voronoi cell distribution. The world is divided by some modulo and another perlin noise function to return a voronoi control point. The seams between biomes show. I thought a simple weight function will do:
Orange point = the sample point which the weights will be calculated according to.
Using cellular noise (some kind of voronoi distribution similar to what I'm looking for, but doesn't blend different biomes):
To clarify vertex height:
float HeightAtPosition(float x, float z)
{
//Returns an array containing information of all the adjacent biome
//control points(mainly their position and their biome type)
BiomeControlPoint[] adjacentControlPoints = GetAdjacentBiomePoints(x, z);
//Returns an array containing values between 0 and 1
//Iputs: An array of all the adjacent biome points, a sample coordinate
//Output: A float array containing the weight of each biome on the
// coordinate(between 0 and 1)
float[] weights = CalcWeights(adjacentControlPoints, new Vector2(x, z));
float finalHeight = 0;
for (int i = 0; i < adjacentControlPoints.Length; i++)
{
finalHeight += adjacentControlPoints[i] * weights[i];
}
return finalHeight;
}
A good solution if GetAdjacentBiomePoints(x, z) and CalcWeights(adjacentControlPoints, new Vector2(x, z)) were more performance efficient. Bilinear interpolation I don't understand.
You could try a weighted voronoi diagram. My php implementation:https://tetramatrix.github.io/awvd/.
You could go the other way:
generate temperature and moisture levels for each pixel
generate how much each biome matches those values
precalculate strength of each biome as a 2d lookup table?
take the X best matches
normalize the strengths (sum is 1)
your a unique noise function combination is weighted sum of the X best biomes
Personally I work with gridmaps and interpolate the biome's valus from a small map with large cells to a large map with small cells. Interpolation is much easier there:
MapInterpolator.java
interpolation classes
Sorry that it is java.

Analyzing the object position using C# generic list

I am computing the distance of an object.
The X and Y position values first stored in two different Lists X and W.
Then I use another List for storing the distance covered by this object. Also, I refresh the lists if their count reaches 10, in order to avoid memory burden.
On the basis of distance value, I have to analyze, if the object is in the static position the distance should not increases. And on the text box display, the computed distance values appears to be static.
Actually, I am using sensors to compute the distance. And due to sensor error even if the object is in the static state the distance value varies. The sensor error threshold is about to be 15cm.
I have developed the logic, However, I receive error:
System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index'
My code is as follows:
void distance()
{
List<double> d = new List<double>();
double sum = 0, sum1 = 0;
for (int i = 1; i < X.Count; i++)
{
//distance computation
if ((d[i] - d[i -1]) > 0.15)
{
sum1 = d.Sum();
sum = sum1 + dis1;
Dis = Math.Round(sum, 3);
}
}
// refresh the Lists when X, W and d List reach the count of 10
}
}
You do it totally wrong. Come up with a method computing a distance for a two given points. That's gonna be a func of signature double -> double -> double or, if you prefer C#, double ComputeDistance(double startPoint, double endPoint).
Then the only thing to do is to apply such a fuction to each pair of points you got. The easiest and most compact way to accomplish that is by means of Linq. It could be done in a regular foreach as well.
Take a note that it would be a way clearer if you will eventually merge your separated lists into a single list. Tuple<double, double> seems to be the best choice including performance.

How to get the fundamental frequency using Harmonic Product Spectrum?

I'm trying to get the pitch from the microphone input. First I have decomposed the signal from time domain to frequency domain through FFT. I have applied Hamming window to the signal before performing FFT. Then I get the complex results of FFT. Then I passed the results to Harmonic product spectrum, where the results get downsampled and then multiplied the downsampled peaks and gave a value as a complex number. Then what should I do to get the fundamental frequency?
public float[] HarmonicProductSpectrum(Complex[] data)
{
Complex[] hps2 = Downsample(data, 2);
Complex[] hps3 = Downsample(data, 3);
Complex[] hps4 = Downsample(data, 4);
Complex[] hps5 = Downsample(data, 5);
float[] array = new float[hps5.Length];
for (int i = 0; i < array.Length; i++)
{
checked
{
array[i] = data[i].X * hps2[i].X * hps3[i].X * hps4[i].X * hps5[i].X;
}
}
return array;
}
public Complex[] Downsample(Complex[] data, int n)
{
Complex[] array = new Complex[Convert.ToInt32(Math.Ceiling(data.Length * 1.0 / n))];
for (int i = 0; i < array.Length; i++)
{
array[i].X = data[i * n].X;
}
return array;
}
I have tried to get the magnitude using,
magnitude[i] = (float)Math.Sqrt(array[i] * array[i] + (data[i].Y * data[i].Y));
inside the for loop in HarmonicProductSpectrum method. Then tried to get the maximum bin using,
float max_mag = float.MinValue;
float max_index = -1;
for (int i = 0; i < array.Length / 2; i++)
if (magnitude[i] > max_mag)
{
max_mag = magnitude[i];
max_index = i;
}
and then I tried to get the frequency using,
var frequency = max_index * 44100 / 1024;
But I was getting garbage values like 1248.926, 1205,859, 2454.785 for the A4 note (440 Hz) and those values don't look like harmonics of A4.
A help would be greatly appreciated.
I implemented harmonic product spectrum in Python to make sure your data and algorithm were working nicely.
Here’s what I see when applying harmonic product spectrum to the full dataset, Hamming-windowed, with 5 downsample–multiply stages:
This is just the bottom kilohertz, but the spectrum is pretty much dead above 1 KHz.
If I chunk up the long audio clip into 8192-sample chunks (with 4096-sample 50% overlap) and Hamming-window each chunk and run HPS on it, this is the matrix of HPS. This is kind of a movie of the HPS spectrum over the entire dataset. The fundamental frequency seems to be quite stable.
The full source code is here—there’s a lot of code that helps chunk the data and visualize the output of HPS running on the chunks, but the core HPS function, starting at def hps(…, is short. But it has a couple of tricks in it.
Given the strange frequencies that you’re finding the peak at, it could be that you’re operating on the full spectrum, from 0 to 44.1 KHz? You want to only keep the “positive” frequencies, i.e., from 0 to 22.05 KHz, and apply the HPS algorithm (downsample–multiply) on that.
But assuming you start out with a positive-frequency-only spectrum, take its magnitude properly, it looks like you should get reasonable results. Try to save out the output of your HarmonicProductSpectrum to see if it’s anything like the above.
Again, the full source code is at https://gist.github.com/fasiha/957035272009eb1c9eb370936a6af2eb. (There I try out another couple of spectral estimator, Welch’s method from Scipy and my port of the Blackman-Tukey spectral estimator. I’m not sure if you are set on implementing HPS or if you would consider other pitch estimators, so I’m leaving the Welch/Blackman-Tukey results there.)
Original I wrote this as a comment but had to keep revising it because it was confusing so here’s it as a mini-answer.
Based on my brief reading of this intro to HPS, I don’t think you’re taking the magnitudes correctly after you find the four decimated responses.
You want:
array[i] = sqrt(data[i] * Complex.conjugate(data[i]) *
hps2[i] * Complex.conjugate(hps2[i]) *
hps3[i] * Complex.conjugate(hps3[i]) *
hps4[i] * Complex.conjugate(hps4[i]) *
hps5[i] * Complex.conjugate(hps5[i])).X;
This uses the sqrt(x * Complex.conjugate(x)) trick to find x’s magnitude, and then multiplies all 5 magnitudes.
(Actually, it moves the sqrt outside the product, so you only do one sqrt, saves some time, but gives the same result. So maybe that’s another trick.)
Final trick: it takes that result’s real part because sometimes due to float accuracy issues, a tiny imaginary component, like 1e-15, survives.
After you do this, array should contain just real floats, and you can apply the max-bin-finding.
If there’s no Conjugate method, then the old-fashioned way should work:
public float mag2(Complex c) { return c.X * c.X + c.Y * c.Y; }
// in HarmonicProductSpectrum
array[i] = sqrt(mag2(data[i]) * mag2(hps2[i]) * mag2(hps3[i]) * mag2(hps4[i]) * mag2(hps5[i]));
There’s algebraic flaws with the two approaches you suggested in the comments below, but the above should be correct. I’m not sure what C# does when you assign a Complex to a float—maybe it uses the real component? I’d have thought that’d be a compiler error, but with the above code, you’re doing the right thing with the complex data, and only assigning a float to array[i].
To get a pitch estimate, you have to divide your sumed bin frequency estimate by the downsampling ratio used for that sum.
Added: You should also sum the magnitudes (abs()), not take the magnitude of the complex sum.
But the harmonic product spectrum algorithm (HPS), especially when using only integer ratios of downsampling, doesn't usually provide better pitch estimation resolution. Instead, it provides a more robust rough pitch estimate (less likely to be fooled by a harmonic) than using a single bare FFT magnitude peak for sequential overtone rich timbres that have weak or missing fundamental spectral content.
If you know how to downsample a spectrum by fractional ratios (using interpolation, etc.), you can try finer grained downsampling to get a better pitch estimate out of HPS. Or you can use an HPS result to inform you of a narrower frequency range in which to search using another pitch or frequency estimation method.

How to find a fitting power law?

Given the following set of xs and ys:
xs = [8294400, 2073600, 921600, 409920]
ys = [124, 433, 853, 1449]
Fitting this with a power law in Excel yields a good approximation:
Excel found a function of the form a(x^b). How can one determine a and b in C#? I tried using Math.Net numerics but I don't see any method that would work for a function of this form. All the functions in the Linear Regression module just find linear coefficients to functions of various forms but none seem to be able to determine an exponent.
The equation you want looks like this:
y = a*x^b
Take the natural log of both sides:
ln(y) = ln(a*x^b) = ln(a) + b*ln(x)
Now you can use linear regression on the new transformed variables (ln(x), ln(y)) and calculate the two parameters you want: ln(a) and b.
In an exponential system, the best way to do a regression is probably by doing a linear regression on a log scale. To clarify, even though your function isn't linear, taking the natural log of both sides of the equation will result in a more linear system
Non-linear function: y = a x^b
This then becomes ln(y) = ln(a x^b) = ln(a) b ln(x)
In Math.NET Numerics, a good way to code it could be:
var y = y.Select(r => Math.Log(r)).ToArray(); // transform y = ln(z)
double[] w = Fit.LinearCombination(xy, z_hat,
d => 1.0,
d => Math.Log(d[0]),
d => Math.Log(d[1]))
Or if you wanted to have it return a function you could use LinearCombinationFunc()
Sources: http://numerics.mathdotnet.com/Regression.html and http://numerics.mathdotnet.com/api/MathNet.Numerics/Fit.htm

how to create and multiply matrixes in c#

Okay, so yesterday at school i was presented with a task in c#, which was create a program to build a Matrix and multiply that matrix by another one. so far i have done this:
List<List<double>> translacao = new List<List<double>>();
translacao[0][0] = 0;
translacao[0][1] = 0;
translacao[0][2] = 4;
translacao[1][0] = 0;
translacao[1][1] = 1;
translacao[1][2] = 6;
translacao[2][0] = 0;
translacao[2][1] = 0;
translacao[2][2] = 8;
I tried with normal arrays like double [,] , but my problem is always the same. From here, how can i multiply this Matrix by another ?? (I know how to multiply matrixes (in paper) but isnt there any method in c# that does that for me ?) the only Matrix classes i found were only able to multiply 3x3 matrixes.
I would say you are gonna have to write your own funciton, maybe even a few overloads for different sizes depending on how crafty your function is.
I am not very good at matrix math but here is somewhat of a process
also this is not c#:
matrix Multiply[][] (matrix a[][], matrix b[][])
{
//check the sizes, i remeber its something that must be done but dont remember the specifics
if (a.width != b.height)
throw WrongSizeException;
matrix result[][];
//do the math:
result[0][0] = a[0][0] * b[0][0]; //again, I don't remeber this stuff
...
...
return result;
}
I hope this gets the right gears turning

Categories

Resources