Browse Source

Regression: Fit.LineThroughOrigin

spatial
Christoph Ruegg 9 years ago
parent
commit
adf8345089
  1. 8
      src/FSharp/Fit.fs
  2. 22
      src/Numerics/Fit.cs
  3. 53
      src/Numerics/LinearRegression/SimpleRegression.cs
  4. 26
      src/UnitTests/FitTests.cs

8
src/FSharp/Fit.fs

@ -47,6 +47,14 @@ module Fit =
/// returning a function y' for the best fitting line.
let lineFunc x y = Fit.LineFunc(x,y) |> tofs
/// Least-Squares fitting the points (x,y) to a line y : x -> b*x,
/// returning its best fitting parameter b.
let lineThroughOrigin x y = Fit.LineThroughOrigin(x,y)
/// Least-Squares fitting the points (x,y) to a line y : x -> b*x,
/// returning a function y' for the best fitting line.
let lineThroughOriginFunc x y = Fit.LineThroughOriginFunc(x,y) |> tofs
/// Least-Squares fitting the points ((x0,x1,...,xk),y) to a linear surface y : X -> p0*x0 + p1*x1 + ... + pk*xk,
/// returning its best fitting parameters as [p0, p1, p2, ..., pk] array.
let multiDim intercept x y = Fit.MultiDim(x,y,intercept)

22
src/Numerics/Fit.cs

@ -3,7 +3,7 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2015 Math.NET
// Copyright (c) 2009-2018 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -61,6 +61,26 @@ namespace MathNet.Numerics
return z => intercept + slope*z;
}
/// <summary>
/// Least-Squares fitting the points (x,y) to a line through origin y : x -> b*x,
/// returning its best fitting parameter b,
/// where the intercept is zero and b the slope.
/// </summary>
public static double LineThroughOrigin(double[] x, double[] y)
{
return SimpleRegression.FitThroughOrigin(x, y);
}
/// <summary>
/// Least-Squares fitting the points (x,y) to a line through origin y : x -> b*x,
/// returning a function y' for the best fitting line.
/// </summary>
public static Func<double, double> LineThroughOriginFunc(double[] x, double[] y)
{
double slope = SimpleRegression.FitThroughOrigin(x, y);
return z => slope * z;
}
/// <summary>
/// Least-Squares fitting the points (X,y) = ((x0,x1,..,xk),y) to a linear surface y : X -> p0*x0 + p1*x1 + ... + pk*xk,
/// returning its best fitting parameters as [p0, p1, p2, ..., pk] array.

53
src/Numerics/LinearRegression/SimpleRegression.cs

@ -3,7 +3,7 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2018 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -91,5 +91,56 @@ namespace MathNet.Numerics.LinearRegression
var xy = samples.UnpackSinglePass();
return Fit(xy.Item1, xy.Item2);
}
/// <summary>
/// Least-Squares fitting the points (x,y) to a line y : x -> b*x,
/// returning its best fitting parameter b,
/// where the intercept is zero and b the slope.
/// </summary>
/// <param name="x">Predictor (independent)</param>
/// <param name="y">Response (dependent)</param>
public static double FitThroughOrigin(double[] x, double[] y)
{
if (x.Length != y.Length)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.Length, y.Length));
}
if (x.Length <= 1)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, 2, x.Length));
}
double mxy = 0.0;
double mxx = 0.0;
for (int i = 0; i < x.Length; i++)
{
mxx += x[i]*x[i];
mxy += x[i]*y[i];
}
return mxy / mxx;
}
/// <summary>
/// Least-Squares fitting the points (x,y) to a line y : x -> b*x,
/// returning its best fitting parameter b,
/// where the intercept is zero and b the slope.
/// </summary>
/// <param name="samples">Predictor-Response samples as tuples</param>
public static double FitThroughOrigin(IEnumerable<Tuple<double, double>> samples)
{
double mxy = 0.0;
double mxx = 0.0;
foreach (var sample in samples)
{
mxx += sample.Item1 * sample.Item1;
mxy += sample.Item1 * sample.Item2;
}
return mxy / mxx;
}
}
}

26
src/UnitTests/FitTests.cs

@ -3,7 +3,7 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2016 Math.NET
// Copyright (c) 2009-2018 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -29,6 +29,8 @@
using System;
using System.Linq;
using MathNet.Numerics.LinearRegression;
using MathNet.Numerics.Statistics;
using NUnit.Framework;
@ -74,6 +76,28 @@ namespace MathNet.Numerics.UnitTests
}
}
[Test]
public void FitsToBestLineThroughOrigin()
{
// Mathematica: Fit[{{1,4.986},{2,2.347},{3,2.061},{4,-2.995},{5,-2.352},{6,-5.782}}, {x}, x]
// -> -0.467791 x
var x = Enumerable.Range(1, 6).Select(Convert.ToDouble).ToArray();
var y = new[] { 4.986, 2.347, 2.061, -2.995, -2.352, -5.782 };
var resp = Fit.LineThroughOrigin(x, y);
Assert.AreEqual(-0.467791, resp, 1e-4);
var resf = Fit.LineThroughOriginFunc(x, y);
foreach (var z in Enumerable.Range(-3, 10))
{
Assert.AreEqual(-0.467791 * z, resf(z), 1e-4);
}
var respSeq = SimpleRegression.FitThroughOrigin(Generate.Map2(x, y, Tuple.Create));
Assert.AreEqual(-0.467791, respSeq, 1e-4);
}
[Test]
public void FitsToMeanOnOrder0Polynomial()
{

Loading…
Cancel
Save