I'm very new to the Math.Net Library and I'm having problems trying to do curve-fitting based on an exponential function. More specifically I intend to use this function:
f(x) = a*exp(b*x) + c*exp(d*x)
Using MATLAB I get pretty good results, as shown in the following image:
MATLAB calculates the following parameters:
f(x) = a*exp(b*x) + c*exp(d*x)
Coefficients (with 95% confidence bounds):
a = 29.6 ( 29.49 , 29.71)
b = 0.000408 ( 0.0003838, 0.0004322)
c = -6.634 ( -6.747 , -6.521)
d = -0.03818 ( -0.03968 , -0.03667)
Is it possible to achieve these results using Math.Net?
Looking at Math.net, it seems that Math.net does various types of regression, whereas your function require some type of iterative method. For instance Gauss-Newton's method where you would use linear regression in each iteration to solve a (overdetermined) system of linear equations, but this would still require some "manual" work with writing the method.
No it appears there is not exponential support at this time. However there's a discussion on Math.NET forums where a maintainer proposes a workaround:
https://discuss.mathdotnet.com/t/exponential-fit/131
Contents duplicated in case link gets broken:
You can, by transforming it, similar to Linearizing non-linear models
by transformation. Something along the lines of the following should
work:
double[] Exponential(double[] x, double[] y,
DirectRegressionMethod method = DirectRegressionMethod.QR)
{
double[] y_hat = Generate.Map(y, Math.Log);
double[] p_hat = Fit.LinearCombination(x, y_hat, method, t => 1.0, t => t);
return new[] {Math.Exp(p_hat[0]), p_hat[1]};
}
Example usage:
double[] x = new[] { 1.0, 2.0, 3.0 };
double[] y = new[] { 2.0, 4.1, 7.9 };
double[] p = Exponential(x,y); // a=1.017, r=0.687
double[] yh = Generate.Map(x,k => p[0]*Math.Exp(p[1]*k)) // 2.02, 4.02, 7.98
Answer is: not yet, I believe. Basically, there is contribution of whole csmpfit package, but it yet to be integrated into Math.Net. You could use it as separate library and then after full integration move to Math.Net. Link http://csmpfit.codeplex.com
Related
I'm trying to use MathNet to calculate weighted linear regression of my data.
The documentation is here.
I'm trying to find a x + b = y such that it would best fit a list of (x,y,w), where w is weight of each point.
var r = WeightedRegression.Weighted(
weightedPoints.Select(p=>new Tuple<double[],double>(new [] { p.LogAvgAmount}, p.Frequency),
weightedPoints.Select(p=>Convert.ToDouble(p.Weight)).ToArray(), false);
As result, in r I'm getting a single point. What I'm expecting is values of a and b.
What am I doing wrong?
WeightedRegression.Weighted expects a predictor matrix as the first parameter, and only the LogAvgAmount is being passed. Try adding a 1 to the list or invoking WeightedRegression.Weighted with intercept: true
var x = weightedPoints.Select(p => new[] {p.LogAvgAmount}).ToArray();
var y = weightedPoints.Select(p => p.Frequency).ToArray();
var w = weightedPoints.Select(p => Convert.ToDouble(p.Weight)).ToArray();
// r1 == r2
var r1 = WeightedRegression.Weighted(weightedPoints.Select(p =>
new[] {1, p.LogAvgAmount}).ToArray(), y, w);
var r2 = WeightedRegression.Weighted(x, y, w, intercept: true);
Using Math.Net Numerics might be a good idea.
Weighted Regression
Sometimes the regression error can be reduced by dampening specific data points. We can achieve this by introducing a weight matrix W into the normal equations XTy=XTXp. Such weight matrices are often diagonal, with a separate weight for each data point on the diagonal.
var p = WeightedRegression.Weighted(X,y,W);
Weighter regression becomes interesting if we can adapt them to the point of interest and e.g. dampen all data points far away. Unfortunately this way the model parameters are dependent on the point of interest t.
1: // warning: preliminary api
2: var p = WeightedRegression.Local(X,y,t,radius,kernel);
You can find more info at:
https://numerics.mathdotnet.com/regression.html
Is there a method to get the ttest-value and P-Value from the StudentT class. I am trying to calculate those values from this library : https://numerics.mathdotnet.com/api/MathNet.Numerics.Distributions/StudentT.htm
The excel equivalent function is T-Test. But I do not have this method in math.net numerics excel function. Below link shows all the excel methods:
https://numerics.mathdotnet.com/api/MathNet.Numerics/ExcelFunctions.htm
Any pointers to get this done from the above library would be of great help.
Thank you...
I don't know how to do this in Math.Net, but I do know how to do it in Meta.Numerics:
Sample sample1 = new Sample(1.0, 2.0, 3.0, 4.0);
Sample sample2 = new Sample(3.0, 4.0, 5.0, 6.0);
TestResult tTest = Sample.StudentTTest(sample1, sample2);
Console.WriteLine("t = {0}", tTest.Statistic);
Console.WriteLine("P = {0} ({1})", tTest.Probability, tTest.Type);
I understand if you aren't interested in changing math libraries, but since your question had gone a while with no answer, I thought I'd chime in.
Here is how to perform a left-tailed t test using the MathNet.Numerics set of libraries.
Assume you have some data in an array and you have already calculated all the required preliminary statistics, as shown below.
int n = 5; //size of sample
double hypotheziedMean = 50.0;
double sampleMean = 50.03;
double sampleSD = 1.5; //sample standard deviation (n-1)
double stdErr = sampleSD / Math.Sqrt(n); //standard error of the mean
double t = (sampleMean - hypotheziedMean) / stdErr; //convert to a standard mean of 0 and SD of 1
StudentT st = new StudentT(0, 1, n-1); //create a standard StudentT object with n-1 DOF
double pVal = st.CumulativeDistribution(t); //left tail pval
I have a grid of data points that I currently use Bilinear interpolation on to find the missing points in the grid. I was pointed in the directions of Kriging aka thee best linear unbiased estimator, but I was unable to find good source code or an algebraic explanation. Does anyone know of any other interpolation methods I could use?
--Update
#Sam Greenhalgh
I have considered Bicubic Interpolation but the results I received using the code example I found seemed off.
Here is the code example for Bicubic
Note I am coding in C# but I welcome examples from other languages as well.
//array 4
double cubicInterpolate(double[] p, double x)
{
return p[1] + 0.5 * x * (p[2] - p[0] + x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
}
//array 4 4
public double bicubicInterpolate(double[][] p, double x, double y)
{
double[] arr = new double[4];
arr[0] = cubicInterpolate(p[0], y);
arr[1] = cubicInterpolate(p[1], y);
arr[2] = cubicInterpolate(p[2], y);
arr[3] = cubicInterpolate(p[3], y);
return cubicInterpolate(arr, x);
}
double[][] p = {
new double[4]{2.728562594,2.30599759,1.907579158,1.739559264},
new double[4]{3.254756633,2.760758022,2.210417411,1.979012766},
new double[4]{4.075740069,3.366434527,2.816093916,2.481060234},
new double[4]{5.430966401,4.896723504,4.219613391,4.004306461}
};
Console.WriteLine(CI.bicubicInterpolate(p, 2, 2));
One widely-used interpolation method is kriging (or Gaussian process regression).
However, the use of kriging is not advised when your data points are on a regular grid. The euclidian distances between data points are used to adjust the parameters of the model. But in a grid, there are much fewer values of distance than in, say, a randomly simulated set of points.
Nevertheless, even if your data points are regularly placed, it could be interesting to give it a try. If you are interested, you can use the following softwares:
DiceKriging package in R language (there exist others like kriging, gstat...)
DACE toolbox in Matlab
STK in Matlab/Octave
And many others (in python for example)...
NOTE: It can be interesting to note (I do not exactly in what context you want to apply kriging) that the kriging interpolation property can very easily be relaxed in order to take into account, for example, possible measurement errors.
If your data points are on a regular grid, I would recommend using a piecewise linear spline in two dimensions. You could fill the data for the rows (x-values) first, then fill the data for the columns (y-values.)
Math.NET Numerics has the piecewise linear spline function that you would need:
MathNet.Numerics.Interpolation.LinearSpline.InterpolateSorted
I'm performing simple linear regression with Math.NET.
I provided a common code sample below. Alternative to this example one can use the Fit class for simple linear regression.
What I additionally want is to specify additional constraints like a fixed y-intercept or force the fit to run throug a fixed point, e.g. (2, 2). How to achieve this in Math.NET?
var xdata = new double[] { 10, 20, 30 };
var ydata = new double[] { 15, 20, 25 };
var X = DenseMatrix.CreateFromColumns(new[] {new DenseVector(xdata.Length, 1), new DenseVector(xdata)});
var y = new DenseVector(ydata);
var p = X.QR().Solve(y);
var a = p[0];
var b = p[1];
You can modify your data set to reflect the constraint , and then use the standard math.Net linear regression
if (x0,y0) is the point through which the regression line must pass,
fit the model y−y0=β(x−x0)+ε, i.e., a linear regression with "no
intercept" on a translated data set.
see here : https://stats.stackexchange.com/questions/12484/constrained-linear-regression-through-a-specified-point
and here : http://en.wikipedia.org/wiki/Linear_least_squares_(mathematics)#Constrained_linear_least_squares
First of all, it you want to force the regression through the origin, you can use LineThroughOrigin or alternativelly LineThroughOriginFunc if what you want is the function itself.
To force the regression to have a desired intercept, I would perform a normal linear regression and get the intercept and slope (knowing these you know everything about your linear function).
With this information, you can compensate the intercept, for example:
If you made your regression in which
intercept = 2
slope = 1
Then you know that your equation would be y = x + 2.
If you want the same function to cross the y axis in 3 (y = x + 3), you would just need to add 1 to the intercept so that
intercept = 3
slope = 1
I want to define a '+' so that I can add a double and a double array:
double[] x = {1.2, 1.4, 1.8};
double[] y = new double[3];
y = x + 0.3;
The result y should equals to
{1.5, 1.7, 2.1}.
That is, each element of x is added 0.3.
I tried, but got compile error. Does that mean there is no way to accomplish this task? '+' can only be applied to two operands with the same type?
You can do:
double[] x = { 1.2, 1.4, 1.8 };
double[] y = x.Select(r => r + 0.3).ToArray();
Which would add 0.3 to each element in x, but if you want to overload + operator then look at operator overloading
Personally, I quite like the solution suggested by #Habib. For the sake of variety, I am going to outline an alternative solution.
If you find yourself working quite a lot with vectors and matrices (i.e. one and two dimensional arrays), then you might find many of the extension methods in the Accord.Math library useful. You can install it with NuGet like so:
Install-Package Accord.Math
Then add a using declaration to your class to bring the extension methods into play
using Accord.Math;
Now you can add a scalar to every element in a vector (array) like so:
double[] x = {1.2, 1.4, 1.8};
double[] y = x.Add(0.3);
Console.WriteLine(y.ToString(DefaultMatrixFormatProvider.CurrentCulture));
which outputs
1.5
1.7
2.1