Browse Source

Basic direct linear regression (simple, multiple, weighted, local)

optimization-1
Christoph Ruegg 13 years ago
parent
commit
3f90613ff7
  1. 4
      src/FSharp/Fit.fs
  2. 70
      src/Numerics/Fit.cs
  3. 169
      src/Numerics/LinearRegression/MultipleRegression.cs
  4. 88
      src/Numerics/LinearRegression/SimpleRegression.cs
  5. 52
      src/Numerics/LinearRegression/Util.cs
  6. 97
      src/Numerics/LinearRegression/WeightedRegression.cs
  7. 4
      src/Numerics/Numerics.csproj
  8. 10
      src/UnitTests/FitTests.cs

4
src/FSharp/Fit.fs

@ -40,8 +40,8 @@ module Fit =
let private tofs (f:Func<_,_>) = fun a -> f.Invoke(a)
/// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
/// returning its best fitting parameters as [a, b] array.
let line x y = let p = Fit.Line(x,y) in (p.[0],p.[1])
/// returning its best fitting parameters as (a, b) tuple.
let line x y = Fit.Line(x,y)
/// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
/// returning a function y' for the best fitting line.

70
src/Numerics/Fit.cs

@ -31,7 +31,7 @@
using System;
using System.Linq;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.Properties;
using MathNet.Numerics.LinearRegression;
namespace MathNet.Numerics
{
@ -42,44 +42,12 @@ namespace MathNet.Numerics
{
/// <summary>
/// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
/// returning its best fitting parameters as [a, b] array.
/// returning its best fitting parameters as [a, b] array,
/// where a is the intercept and b the slope.
/// </summary>
public static double[] Line(double[] x, double[] y)
public static Tuple<double, double> Line(double[] x, double[] y)
{
if (x == null) throw new ArgumentNullException("x");
if (y == null) throw new ArgumentNullException("y");
if (x.Length != y.Length) throw new ArgumentException(Resources.ArgumentVectorsSameLength);
if (x.Length <= 1) throw new ArgumentException(string.Format(Resources.ArrayTooSmall, 2));
// First Pass: Mean (Less robust but faster than ArrayStatistics.Mean)
double mx = 0.0;
double my = 0.0;
for (int i = 0; i < x.Length; i++)
{
mx += x[i];
my += y[i];
}
mx /= x.Length;
my /= y.Length;
// Second Pass: Covariance/Variance
double covariance = 0.0;
double variance = 0.0;
for (int i = 0; i < x.Length; i++)
{
double diff = x[i] - mx;
covariance += diff*(y[i] - my);
variance += diff*diff;
}
var b = covariance/variance;
return new[] {my - b*mx, b};
// General Solution:
//return DenseMatrix
// .OfColumns(x.Length, 2, new[] {DenseVector.Create(x.Length, i => 1.0), new DenseVector(x)})
// .QR(QRMethod.Thin).Solve(new DenseVector(y))
// .ToArray();
return SimpleRegression.Fit(x, y);
}
/// <summary>
@ -88,9 +56,9 @@ namespace MathNet.Numerics
/// </summary>
public static Func<double, double> LineFunc(double[] x, double[] y)
{
var parameters = Line(x, y);
double a = parameters[0], b = parameters[1];
return z => a + b*z;
var parameters = SimpleRegression.Fit(x, y);
double intercept = parameters.Item1, slope = parameters.Item2;
return z => intercept + slope*z;
}
/// <summary>
@ -99,10 +67,8 @@ namespace MathNet.Numerics
/// </summary>
public static double[] Polynomial(double[] x, double[] y, int order)
{
return DenseMatrix
.OfColumns(x.Length, order + 1, Enumerable.Range(0, order + 1).Select(j => DenseVector.Create(x.Length, i => Math.Pow(x[i], j))))
.QR().Solve(new DenseVector(y))
.ToArray();
var design = DenseMatrix.OfColumns(x.Length, order + 1, Enumerable.Range(0, order + 1).Select(j => DenseVector.Create(x.Length, i => Math.Pow(x[i], j))));
return MultipleRegression.QR(design, new DenseVector(y)).ToArray();
}
/// <summary>
@ -121,10 +87,8 @@ namespace MathNet.Numerics
/// </summary>
public static double[] LinearCombination(double[] x, double[] y, params Func<double,double>[] functions)
{
return DenseMatrix
.OfColumns(x.Length, functions.Length, functions.Select(f => DenseVector.Create(x.Length, i => f(x[i]))))
.QR().Solve(new DenseVector(y))
.ToArray();
var design = DenseMatrix.OfColumns(x.Length, functions.Length, functions.Select(f => DenseVector.Create(x.Length, i => f(x[i]))));
return MultipleRegression.QR(design, new DenseVector(y)).ToArray();
}
/// <summary>
@ -143,10 +107,7 @@ namespace MathNet.Numerics
/// </summary>
public static double[] LinearMultiDim(double[][] x, double[] y, params Func<double[], double>[] functions)
{
return DenseMatrix
.OfRows(x.Length, functions.Length, x.Select(xi => functions.Select(f => f(xi))))
.QR().Solve(new DenseVector(y))
.ToArray();
return MultipleRegression.QR(x.Select(xi => functions.Select(f => f(xi)).ToArray()).ToArray(), y);
}
/// <summary>
@ -165,10 +126,7 @@ namespace MathNet.Numerics
/// </summary>
public static double[] LinearGeneric<T>(T[] x, double[] y, params Func<T, double>[] functions)
{
return DenseMatrix
.OfRows(x.Length, functions.Length, x.Select(xi => functions.Select(f => f(xi))))
.QR().Solve(new DenseVector(y))
.ToArray();
return MultipleRegression.QR(x.Select(xi => functions.Select(f => f(xi)).ToArray()).ToArray(), y);
}
/// <summary>

169
src/Numerics/LinearRegression/MultipleRegression.cs

@ -0,0 +1,169 @@
// <copyright file="MultipleRegression.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.LinearRegression
{
public static class MultipleRegression
{
/// <summary>
/// Find the model parameters β such that X*β with predictor X becomes as close to response Y as possible, with least squares residuals.
/// Uses the cholesky decomposition of the normal equations.
/// </summary>
/// <param name="x">Predictor matrix X</param>
/// <param name="y">Response vector Y</param>
/// <returns>Best fitting vector for model parameters β</returns>
public static Vector<T> NormalEquations<T>(Matrix<T> x, Vector<T> y) where T : struct, IEquatable<T>, IFormattable
{
return x.TransposeThisAndMultiply(x).Cholesky().Solve(x.Transpose()*y);
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses the cholesky decomposition of the normal equations.
/// </summary>
/// <param name="x">List of predictor-arrays.</param>
/// <param name="y">List of responses</param>
/// <param name="intercept">True if an intercept should be added as first artificial perdictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] NormalEquations<T>(T[][] x, T[] y, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var predictor = Matrix<T>.Build.DenseMatrixOfRowArrays(x);
if (intercept)
{
predictor = predictor.InsertColumn(0, Vector<T>.Build.DenseVector(predictor.RowCount, Vector<T>.One));
}
var response = Matrix<T>.Build.DenseVector(y);
return predictor.TransposeThisAndMultiply(predictor).Cholesky().Solve(predictor.Transpose()*response).ToArray();
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses the cholesky decomposition of the normal equations.
/// </summary>
/// <param name="samples">Sequence of predictor-arrays and their response.</param>
/// <param name="intercept">True if an intercept should be added as first artificial perdictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] NormalEquations<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var xy = samples.UnpackSinglePass();
return NormalEquations(xy.Item1, xy.Item2, intercept);
}
/// <summary>
/// Find the model parameters β such that X*β with predictor X becomes as close to response Y as possible, with least squares residuals.
/// Uses an orthogonal decomposition and is therefore more numerically stable than the normal equations but also slower.
/// </summary>
/// <param name="x">Predictor matrix X</param>
/// <param name="y">Response vector Y</param>
/// <returns>Best fitting vector for model parameters β</returns>
public static Vector<T> QR<T>(Matrix<T> x, Vector<T> y) where T : struct, IEquatable<T>, IFormattable
{
return x.QR().Solve(y);
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses an orthogonal decomposition and is therefore more numerically stable than the normal equations but also slower.
/// </summary>
/// <param name="x">List of predictor-arrays.</param>
/// <param name="y">List of responses</param>
/// <param name="intercept">True if an intercept should be added as first artificial perdictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] QR<T>(T[][] x, T[] y, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var predictor = Matrix<T>.Build.DenseMatrixOfRowArrays(x);
if (intercept)
{
predictor = predictor.InsertColumn(0, Vector<T>.Build.DenseVector(predictor.RowCount, Vector<T>.One));
}
return predictor.QR().Solve(Matrix<T>.Build.DenseVector(y)).ToArray();
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses an orthogonal decomposition and is therefore more numerically stable than the normal equations but also slower.
/// </summary>
/// <param name="samples">Sequence of predictor-arrays and their response.</param>
/// <param name="intercept">True if an intercept should be added as first artificial perdictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] QR<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var xy = samples.UnpackSinglePass();
return QR(xy.Item1, xy.Item2, intercept);
}
/// <summary>
/// Find the model parameters β such that X*β with predictor X becomes as close to response Y as possible, with least squares residuals.
/// Uses a singular value decomposition and is therefore more numerically stable (especially if ill-conditioned) than the normal equations or QR but also slower.
/// </summary>
/// <param name="x">Predictor matrix X</param>
/// <param name="y">Response vector Y</param>
/// <returns>Best fitting vector for model parameters β</returns>
public static Vector<T> Svd<T>(Matrix<T> x, Vector<T> y) where T : struct, IEquatable<T>, IFormattable
{
return x.Svd().Solve(y);
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses a singular value decomposition and is therefore more numerically stable (especially if ill-conditioned) than the normal equations or QR but also slower.
/// </summary>
/// <param name="x">List of predictor-arrays.</param>
/// <param name="y">List of responses</param>
/// <param name="intercept">True if an intercept should be added as first artificial perdictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] Svd<T>(T[][] x, T[] y, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var predictor = Matrix<T>.Build.DenseMatrixOfRowArrays(x);
if (intercept)
{
predictor = predictor.InsertColumn(0, Vector<T>.Build.DenseVector(predictor.RowCount, Vector<T>.One));
}
return predictor.Svd().Solve(Matrix<T>.Build.DenseVector(y)).ToArray();
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses a singular value decomposition and is therefore more numerically stable (especially if ill-conditioned) than the normal equations or QR but also slower.
/// </summary>
/// <param name="samples">Sequence of predictor-arrays and their response.</param>
/// <param name="intercept">True if an intercept should be added as first artificial perdictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] Svd<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var xy = samples.UnpackSinglePass();
return Svd(xy.Item1, xy.Item2, intercept);
}
}
}

88
src/Numerics/LinearRegression/SimpleRegression.cs

@ -0,0 +1,88 @@
// <copyright file="SimpleRegression.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearRegression
{
public static class SimpleRegression
{
/// <summary>
/// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
/// returning its best fitting parameters as (a, b) tuple,
/// where a is the intercept and b the slope.
/// </summary>
/// <param name="x">Predictor (independent)</param>
/// <param name="y">Response (dependent)</param>
public static Tuple<double, double> Fit(double[] x, double[] y)
{
if (x.Length != y.Length) throw new ArgumentException(Resources.ArgumentVectorsSameLength);
if (x.Length <= 1) throw new ArgumentException(string.Format(Resources.ArrayTooSmall, 2));
// First Pass: Mean (Less robust but faster than ArrayStatistics.Mean)
double mx = 0.0;
double my = 0.0;
for (int i = 0; i < x.Length; i++)
{
mx += x[i];
my += y[i];
}
mx /= x.Length;
my /= y.Length;
// Second Pass: Covariance/Variance
double covariance = 0.0;
double variance = 0.0;
for (int i = 0; i < x.Length; i++)
{
double diff = x[i] - mx;
covariance += diff*(y[i] - my);
variance += diff*diff;
}
var b = covariance/variance;
return new Tuple<double, double>(my - b*mx, b);
}
/// <summary>
/// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
/// returning its best fitting parameters as (a, b) tuple,
/// where a is the intercept and b the slope.
/// </summary>
/// <param name="samples">Predictor-Response samples as tuples</param>
public static Tuple<double, double> Fit(IEnumerable<Tuple<double, double>> samples)
{
var xy = samples.UnpackSinglePass();
return Fit(xy.Item1, xy.Item2);
}
}
}

52
src/Numerics/LinearRegression/Util.cs

@ -0,0 +1,52 @@
// <copyright file="Util.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
namespace MathNet.Numerics.LinearRegression
{
internal static class Util
{
public static Tuple<TU[], TV[]> UnpackSinglePass<TU, TV>(this IEnumerable<Tuple<TU, TV>> samples)
{
var u = new List<TU>();
var v = new List<TV>();
foreach (var tuple in samples)
{
u.Add(tuple.Item1);
v.Add(tuple.Item2);
}
return new Tuple<TU[], TV[]>(u.ToArray(), v.ToArray());
}
}
}

97
src/Numerics/LinearRegression/WeightedRegression.cs

@ -0,0 +1,97 @@
// <copyright file="LocallyWeightedRegression.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Storage;
namespace MathNet.Numerics.LinearRegression
{
public static class WeightedRegression
{
/// <summary>
/// Weighted Linear Regression using normal equations.
/// </summary>
public static Vector<T> Weighted<T>(Matrix<T> x, Vector<T> y, Matrix<T> w) where T : struct, IEquatable<T>, IFormattable
{
return x.TransposeThisAndMultiply(w * x).Cholesky().Solve(x.Transpose() * (w * y));
}
/// <summary>
/// Weighted Linear Regression using normal equations.
/// </summary>
/// <param name="intercept">True if an intercept should be added as first artificial perdictor value. Default = false.</param>
public static T[] Weighted<T>(T[][] x, T[] y, T[] w, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var predictor = Matrix<T>.Build.DenseMatrixOfRowArrays(x);
if (intercept)
{
predictor = predictor.InsertColumn(0, Vector<T>.Build.DenseVector(predictor.RowCount, Vector<T>.One));
}
var response = Matrix<T>.Build.DenseVector(y);
var weights = Matrix<T>.Build.DiagonalMatrix(new DiagonalMatrixStorage<T>(predictor.RowCount, predictor.RowCount, w));
return predictor.TransposeThisAndMultiply(weights * predictor).Cholesky().Solve(predictor.Transpose() * (weights * response)).ToArray();
}
/// <summary>
/// Weighted Linear Regression using normal equations.
/// </summary>
/// <param name="intercept">True if an intercept should be added as first artificial perdictor value. Default = false.</param>
public static T[] Weighted<T>(IEnumerable<Tuple<T[], T>> samples, T[] w, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var xy = samples.UnpackSinglePass();
return Weighted(xy.Item1, xy.Item2, w, intercept);
}
/// <summary>
/// Locally-Weighted Linear Regression using normal equations.
/// </summary>
public static Vector<T> Local<T>(Matrix<T> x, Vector<T> y, Vector<T> t, Func<Vector<T>, Vector<T>, T> kernel) where T : struct, IEquatable<T>, IFormattable
{
// TODO: Kernel definition is a bit weird as it includes computing the difference norm
// We can make this more common once we change the norm to always be of type double around LA.
var w = Matrix<T>.Build.DenseMatrix(x.RowCount, x.RowCount);
for (int i = 0; i < x.RowCount; i++)
{
w.At(i, i, kernel(t, x.Row(i)));
}
return Weighted(x, y, w);
}
public static Func<Vector<double>, Vector<double>, double> GaussianKernel(double radius)
{
// TODO: see above...
var d = -2.0*radius*radius;
return (t, x) => Math.Exp(Distance.SSD(x, t)/d);
}
}
}

4
src/Numerics/Numerics.csproj

@ -132,6 +132,10 @@
<Compile Include="LinearAlgebra\Solvers\Iterator.cs" />
<Compile Include="LinearAlgebra\Solvers\IterationCountStopCriterium.cs" />
<Compile Include="LinearAlgebra\Solvers\SolverSetup.cs" />
<Compile Include="LinearRegression\MultipleRegression.cs" />
<Compile Include="LinearRegression\WeightedRegression.cs" />
<Compile Include="LinearRegression\SimpleRegression.cs" />
<Compile Include="LinearRegression\Util.cs" />
<Compile Include="Providers\LinearAlgebra\Acml\AcmlLinearAlgebraProvider.Complex.cs" />
<Compile Include="Providers\LinearAlgebra\Acml\AcmlLinearAlgebraProvider.Complex32.cs" />
<Compile Include="Providers\LinearAlgebra\Acml\AcmlLinearAlgebraProvider.Double.cs" />

10
src/UnitTests/FitTests.cs

@ -45,9 +45,8 @@ namespace MathNet.Numerics.UnitTests
var y = x.Select(z => 4.0 - 1.5*z).ToArray();
var resp = Fit.Line(x, y);
Assert.AreEqual(2, resp.Length);
Assert.AreEqual(4.0, resp[0], 1e-12);
Assert.AreEqual(-1.5, resp[1], 1e-12);
Assert.AreEqual(4.0, resp.Item1, 1e-12);
Assert.AreEqual(-1.5, resp.Item2, 1e-12);
var resf = Fit.LineFunc(x, y);
foreach (var z in Enumerable.Range(-3, 10))
@ -66,9 +65,8 @@ namespace MathNet.Numerics.UnitTests
var y = new[] {4.986, 2.347, 2.061, -2.995, -2.352, -5.782};
var resp = Fit.Line(x, y);
Assert.AreEqual(2, resp.Length);
Assert.AreEqual(7.01013, resp[0], 1e-4);
Assert.AreEqual(-2.08551, resp[1], 1e-4);
Assert.AreEqual(7.01013, resp.Item1, 1e-4);
Assert.AreEqual(-2.08551, resp.Item2, 1e-4);
var resf = Fit.LineFunc(x, y);
foreach (var z in Enumerable.Range(-3, 10))

Loading…
Cancel
Save