Browse Source

Regression: more helpful exceptions and messages

netstandard
Christoph Ruegg 11 years ago
parent
commit
30421c7033
  1. 13
      src/Numerics/Fit.cs
  2. 101
      src/Numerics/LinearRegression/MultipleRegression.cs
  3. 12
      src/Numerics/LinearRegression/SimpleRegression.cs
  4. 38
      src/Numerics/Properties/Resources.Designer.cs
  5. 6
      src/Numerics/Properties/Resources.resx

13
src/Numerics/Fit.cs

@ -3,9 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
//
//
// Copyright (c) 2009-2015 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
@ -14,10 +14,10 @@
// 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
@ -94,6 +94,7 @@ namespace MathNet.Numerics
/// <summary>
/// Least-Squares fitting the points (x,y) to a k-order polynomial y : x -> p0 + p1*x + p2*x^2 + ... + pk*x^k,
/// returning its best fitting parameters as [p0, p1, p2, ..., pk] array, compatible with Evaluate.Polynomial.
/// A polynomial with order/degree k has (k+1) coefficients and thus requires at least (k+1) samples.
/// </summary>
public static double[] Polynomial(double[] x, double[] y, int order, DirectRegressionMethod method = DirectRegressionMethod.QR)
{
@ -104,6 +105,7 @@ namespace MathNet.Numerics
/// <summary>
/// Least-Squares fitting the points (x,y) to a k-order polynomial y : x -> p0 + p1*x + p2*x^2 + ... + pk*x^k,
/// returning a function y' for the best fitting polynomial.
/// A polynomial with order/degree k has (k+1) coefficients and thus requires at least (k+1) samples.
/// </summary>
public static Func<double, double> PolynomialFunc(double[] x, double[] y, int order, DirectRegressionMethod method = DirectRegressionMethod.QR)
{
@ -114,6 +116,7 @@ namespace MathNet.Numerics
/// <summary>
/// Weighted Least-Squares fitting the points (x,y) and weights w to a k-order polynomial y : x -> p0 + p1*x + p2*x^2 + ... + pk*x^k,
/// returning its best fitting parameters as [p0, p1, p2, ..., pk] array, compatible with Evaluate.Polynomial.
/// A polynomial with order/degree k has (k+1) coefficients and thus requires at least (k+1) samples.
/// </summary>
public static double[] PolynomialWeighted(double[] x, double[] y, double[] w, int order)
{

101
src/Numerics/LinearRegression/MultipleRegression.cs

@ -3,9 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2014 Math.NET
//
//
// Copyright (c) 2009-2015 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
@ -14,10 +14,10 @@
// 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
@ -31,6 +31,7 @@
using System;
using System.Collections.Generic;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearRegression
{
@ -135,6 +136,16 @@ namespace MathNet.Numerics.LinearRegression
/// <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
{
if (x.RowCount != y.Count)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.Count));
}
if (x.ColumnCount > y.Count)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.Count));
}
return x.TransposeThisAndMultiply(x).Cholesky().Solve(x.TransposeThisAndMultiply(y));
}
@ -147,6 +158,16 @@ namespace MathNet.Numerics.LinearRegression
/// <returns>Best fitting vector for model parameters β</returns>
public static Matrix<T> NormalEquations<T>(Matrix<T> x, Matrix<T> y) where T : struct, IEquatable<T>, IFormattable
{
if (x.RowCount != y.RowCount)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.RowCount));
}
if (x.ColumnCount > y.RowCount)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.RowCount));
}
return x.TransposeThisAndMultiply(x).Cholesky().Solve(x.TransposeThisAndMultiply(y));
}
@ -166,6 +187,16 @@ namespace MathNet.Numerics.LinearRegression
predictor = predictor.InsertColumn(0, Vector<T>.Build.Dense(predictor.RowCount, Vector<T>.One));
}
if (predictor.RowCount != y.Length)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, predictor.RowCount, y.Length));
}
if (predictor.ColumnCount > y.Length)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, predictor.ColumnCount, y.Length));
}
var response = Vector<T>.Build.Dense(y);
return predictor.TransposeThisAndMultiply(predictor).Cholesky().Solve(predictor.TransposeThisAndMultiply(response)).ToArray();
}
@ -192,6 +223,16 @@ namespace MathNet.Numerics.LinearRegression
/// <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
{
if (x.RowCount != y.Count)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.Count));
}
if (x.ColumnCount > y.Count)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.Count));
}
return x.QR().Solve(y);
}
@ -204,6 +245,16 @@ namespace MathNet.Numerics.LinearRegression
/// <returns>Best fitting vector for model parameters β</returns>
public static Matrix<T> QR<T>(Matrix<T> x, Matrix<T> y) where T : struct, IEquatable<T>, IFormattable
{
if (x.RowCount != y.RowCount)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.RowCount));
}
if (x.ColumnCount > y.RowCount)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.RowCount));
}
return x.QR().Solve(y);
}
@ -223,6 +274,16 @@ namespace MathNet.Numerics.LinearRegression
predictor = predictor.InsertColumn(0, Vector<T>.Build.Dense(predictor.RowCount, Vector<T>.One));
}
if (predictor.RowCount != y.Length)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, predictor.RowCount, y.Length));
}
if (predictor.ColumnCount > y.Length)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, predictor.ColumnCount, y.Length));
}
return predictor.QR().Solve(Vector<T>.Build.Dense(y)).ToArray();
}
@ -248,6 +309,16 @@ namespace MathNet.Numerics.LinearRegression
/// <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
{
if (x.RowCount != y.Count)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.Count));
}
if (x.ColumnCount > y.Count)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.Count));
}
return x.Svd().Solve(y);
}
@ -260,6 +331,16 @@ namespace MathNet.Numerics.LinearRegression
/// <returns>Best fitting vector for model parameters β</returns>
public static Matrix<T> Svd<T>(Matrix<T> x, Matrix<T> y) where T : struct, IEquatable<T>, IFormattable
{
if (x.RowCount != y.RowCount)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.RowCount));
}
if (x.ColumnCount > y.RowCount)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.RowCount));
}
return x.Svd().Solve(y);
}
@ -279,6 +360,16 @@ namespace MathNet.Numerics.LinearRegression
predictor = predictor.InsertColumn(0, Vector<T>.Build.Dense(predictor.RowCount, Vector<T>.One));
}
if (predictor.RowCount != y.Length)
{
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, predictor.RowCount, y.Length));
}
if (predictor.ColumnCount > y.Length)
{
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, predictor.ColumnCount, y.Length));
}
return predictor.Svd().Solve(Vector<T>.Build.Dense(y)).ToArray();
}

12
src/Numerics/LinearRegression/SimpleRegression.cs

@ -3,9 +3,9 @@
// 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
@ -14,10 +14,10 @@
// 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
@ -47,12 +47,12 @@ namespace MathNet.Numerics.LinearRegression
{
if (x.Length != y.Length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.Length, y.Length));
}
if (x.Length <= 1)
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, 2));
throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, 2, x.Length));
}
// First Pass: Mean (Less robust but faster than ArrayStatistics.Mean)

38
src/Numerics/Properties/Resources.Designer.cs

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34209
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@ -12,8 +12,8 @@ using System.Reflection;
namespace MathNet.Numerics.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
@ -25,15 +25,15 @@ namespace MathNet.Numerics.Properties {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
@ -56,7 +56,7 @@ namespace MathNet.Numerics.Properties {
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
@ -394,7 +394,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentOutOfRangeSmaller", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} must be smaller than or equal to {1}..
/// </summary>
@ -403,7 +403,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentOutOfRangeSmallerEqual", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The chosen parameter set is invalid (probably some value is out of range)..
/// </summary>
@ -864,6 +864,15 @@ namespace MathNet.Numerics.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to A regression of the requested order requires at least {0} samples. Only {1} samples have been provided. .
/// </summary>
public static string RegressionNotEnoughSamples {
get {
return ResourceManager.GetString("RegressionNotEnoughSamples", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The algorithm has failed, exceeded the number of iterations allowed or there is no root within the provided bounds..
/// </summary>
@ -909,6 +918,15 @@ namespace MathNet.Numerics.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to All sample vectors must have the same length. However, vectors with disagreeing length {0} and {1} have been provided. A sample with index i is given by the value at index i of each provided vector..
/// </summary>
public static string SampleVectorsSameLength {
get {
return ResourceManager.GetString("SampleVectorsSameLength", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to U is singular, and the inversion could not be completed..
/// </summary>

6
src/Numerics/Properties/Resources.resx

@ -436,4 +436,10 @@
<data name="SingularUMatrixWithElement" xml:space="preserve">
<value>U is singular, and the inversion could not be completed. The {0}-th diagonal element of the factor U is zero.</value>
</data>
<data name="RegressionNotEnoughSamples" xml:space="preserve">
<value>A regression of the requested order requires at least {0} samples. Only {1} samples have been provided. </value>
</data>
<data name="SampleVectorsSameLength" xml:space="preserve">
<value>All sample vectors must have the same length. However, vectors with disagreeing length {0} and {1} have been provided. A sample with index i is given by the value at index i of each provided vector.</value>
</data>
</root>
Loading…
Cancel
Save