Skip to content
This repository has been archived by the owner on Nov 19, 2020. It is now read-only.

Commit

Permalink
GH-649: Add an Example for NonNegativeLeastSquares Class
Browse files Browse the repository at this point in the history
  • Loading branch information
cesarsouza committed Jun 18, 2017
1 parent 998c75d commit ab648d3
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,18 @@ namespace Accord.Statistics.Models.Regression.Linear
/// to model a plane as an equation in the form ax + by + c = z. </para>
///
/// <code source="Unit Tests\Accord.Tests.Statistics\Models\Regression\MultipleLinearRegressionTest.cs" region="doc_learn" />
///
/// <para>
/// The next example shows how to fit a multiple linear regression model with the
/// additional constraint that none of its coefficients should be negative. For this
/// we can use the <see cref="NonNegativeLeastSquares"/> learning algorithm instead of
/// the <see cref="OrdinaryLeastSquares"/> used above.</para>
///
/// <code source="Unit Tests\Accord.Tests.Statistics\Models\Regression\NonLinear\Fitting\NonNegativeLeastSquaresTest.cs" region="doc_learn" />
/// </example>
///
/// <seealso cref="OrdinaryLeastSquares"/>
/// <seealso cref="NonNegativeLeastSquares"/>
/// <seealso cref="SimpleLinearRegression"/>
/// <seealso cref="MultivariateLinearRegression"/>
/// <seealso cref="MultipleLinearRegressionAnalysis"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ namespace Accord.Statistics.Models.Regression.Fitting
using System.Threading;
using Accord.Math;
using Accord.Statistics.Models.Regression.Linear;
using MachineLearning;
using Accord.MachineLearning;
using Accord.Math.Optimization.Losses;

/// <summary>
/// Non-negative Least Squares for <see cref="NonlinearRegression"/> optimization.
/// Non-negative Least Squares for <see cref="MultipleLinearRegression"/> optimization.
/// </summary>
///
/// <remarks>
Expand All @@ -47,8 +47,21 @@ namespace Accord.Statistics.Models.Regression.Fitting
/// </list></para>
/// </remarks>
///
/// <example>
/// <para>
/// The following example shows how to fit a multiple linear regression model with the
/// additional constraint that none of its coefficients should be negative. For this
/// we can use the <see cref="NonNegativeLeastSquares"/> learning algorithm instead of
/// the <see cref="OrdinaryLeastSquares"/> used above.</para>
///
/// <code source="Unit Tests\Accord.Tests.Statistics\Models\Regression\NonLinear\Fitting\NonNegativeLeastSquaresTest.cs" region="doc_learn" />
/// </example>
///
/// <seealso cref="OrdinaryLeastSquares"/>
/// <seealso cref="MultipleLinearRegression"/>
///
#pragma warning disable 612, 618
public class NonNegativeLeastSquares : IRegressionFitting,
public class NonNegativeLeastSquares : IRegressionFitting,
ISupervisedLearning<MultipleLinearRegression, double[], double>
#pragma warning restore 612, 618
{
Expand Down Expand Up @@ -105,13 +118,26 @@ public CancellationToken Token
set { token = value; }
}

/// <summary>
/// Initializes a new instance of the <see cref="NonNegativeLeastSquares"/> class.
/// </summary>
///
public NonNegativeLeastSquares()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="NonNegativeLeastSquares"/> class.
/// </summary>
///
/// <param name="regression">The regression to be fitted.</param>
///
public NonNegativeLeastSquares(MultipleLinearRegression regression)
{
init(regression);
}

private void init(MultipleLinearRegression regression)
{
this.regression = regression;
this.cols = regression.Weights.Length;
Expand Down Expand Up @@ -152,6 +178,9 @@ public MultipleLinearRegression Learn(double[][] x, double[] y, double[] weights
if (weights != null)
throw new ArgumentException(Accord.Properties.Resources.NotSupportedWeights, "weights");

if (this.regression == null)
init(new MultipleLinearRegression { NumberOfInputs = x.Columns() });

this.X = x;
this.scatter = X.TransposeAndDot(X);
this.vector = X.TransposeAndDot(y);
Expand Down Expand Up @@ -219,7 +248,7 @@ private void InnerLoop(double[] x)
x = (s.Subtract(x)).Multiply(alpha).Add(x);

// 4.4 Update R and P
for (var i = 0; i < p.Count; )
for (var i = 0; i < p.Count;)
{
int pItem = p[i];
if (System.Math.Abs(x[pItem]) < double.Epsilon)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,14 @@ namespace Accord.Tests.Statistics.Models.Regression
using NUnit.Framework;
using Accord.Statistics.Models.Regression.Fitting;
using Accord.Statistics.Models.Regression.Linear;
using Accord.Math.Optimization.Losses;

[TestFixture]
public class NonNegativeLeastSquaresTests
{
[Test]
public void ExampleTest()
{
// Suppose we would like to map the continuous values in the
// second column to the integer values in the first column.
var inputs = new[]
{
new[] { 1.0, 1.0 },
Expand All @@ -64,8 +63,6 @@ public void ExampleTest()
[Test]
public void ExampleTest2()
{
// Suppose we would like to map the continuous values in the
// second column to the integer values in the first column.
var inputs = new[]
{
new[] { 1.0, 1.0, 1.0 },
Expand All @@ -86,13 +83,15 @@ public void ExampleTest2()
Assert.AreEqual(0.1, nnls.Coefficients[0], 1e-3);
Assert.AreEqual(0.5, nnls.Coefficients[1], 1e-3);
Assert.AreEqual(0.13, nnls.Coefficients[2], 1e-3);

Assert.AreEqual(0.1, regression.Coefficients[0], 1e-3);
Assert.AreEqual(0.5, regression.Coefficients[1], 1e-3);
Assert.AreEqual(0.13, regression.Coefficients[2], 1e-3);
}

[Test]
public void ExampleTest3()
{
// Suppose we would like to map the continuous values in the
// second column to the integer values in the first column.
var inputs = new[]
{
new[] { 1.0, 1.0, 1.0, 1.0 },
Expand All @@ -114,13 +113,15 @@ public void ExampleTest3()
Assert.AreEqual(0.5, nnls.Coefficients[1], 1e-3);
Assert.AreEqual(0.13, nnls.Coefficients[2], 1e-3);
Assert.AreEqual(0, nnls.Coefficients[3], 1e-3);

Assert.AreEqual(0.1, regression.Coefficients[0], 1e-3);
Assert.AreEqual(0.5, regression.Coefficients[1], 1e-3);
Assert.AreEqual(0.13, regression.Coefficients[2], 1e-3);
}

[Test]
public void ExampleTest4()
{
// Suppose we would like to map the continuous values in the
// second column to the integer values in the first column.
var inputs = new[]
{
new[] { 1.0, 1.0, 1.0 },
Expand All @@ -141,6 +142,56 @@ public void ExampleTest4()
Assert.AreEqual(0.1, nnls.Coefficients[0], 1e-3);
Assert.AreEqual(0, nnls.Coefficients[1], 1e-3);
Assert.AreEqual(0.13, nnls.Coefficients[2], 1e-3);

Assert.AreEqual(0.1, regression.Coefficients[0], 1e-3);
Assert.AreEqual(0, regression.Coefficients[1], 1e-3);
Assert.AreEqual(0.13, regression.Coefficients[2], 1e-3);
}

[Test]
public void learn_test()
{
#region doc_learn
// Declare training samples
var inputs = new double[][]
{
new[] { 1.0, 1.0, 1.0 },
new[] { 2.0, 4.0, 8.0 },
new[] { 3.0, 9.0, 27.0 },
new[] { 4.0, 16.0, 64.0 },
};

var outputs = new double[] { 0.23, 1.24, 3.81, 8.72 };

// Create a NN LS learning algorithm
var nnls = new NonNegativeLeastSquares()
{
MaxIterations = 100
};

// Use the algorithm to learn a multiple linear regression
MultipleLinearRegression regression = nnls.Learn(inputs, outputs);

// None of the regression coefficients should be negative:
double[] coefficients = regression.Weights; // should be

// Check the quality of the regression:
double[] prediction = regression.Transform(inputs);

double error = new SquareLoss(expected: outputs)
.Loss(actual: prediction); // should be

#endregion

Assert.AreEqual(0, error, 1e-10);

Assert.AreEqual(0.1, nnls.Coefficients[0], 1e-3);
Assert.AreEqual(0, nnls.Coefficients[1], 1e-3);
Assert.AreEqual(0.13, nnls.Coefficients[2], 1e-3);

Assert.AreEqual(0.1, regression.Coefficients[0], 1e-3);
Assert.AreEqual(0, regression.Coefficients[1], 1e-3);
Assert.AreEqual(0.13, regression.Coefficients[2], 1e-3);
}
}
}

0 comments on commit ab648d3

Please sign in to comment.