16

有谁知道在 C# 中进行多重线性回归的有效方法,其中联立方程的数量可能在 1000 个(具有 3 或 4 个不同的输入)。在阅读了这篇关于多元线性回归的文章后,我尝试使用矩阵方程来实现它:

Matrix y = new Matrix(
    new double[,]{{745},
                  {895},
                  {442},
                  {440},
                  {1598}});

Matrix x = new Matrix(
     new double[,]{{1, 36, 66},
                 {1, 37, 68},
                 {1, 47, 64},
                 {1, 32, 53},
                 {1, 1, 101}});

Matrix b = (x.Transpose() * x).Inverse() * x.Transpose() * y;

for (int i = 0; i < b.Rows; i++)
{
  Trace.WriteLine("INFO: " + b[i, 0].ToDouble());
}

然而,由于矩阵求逆运算,它不能很好地扩展到 1000 个方程的规模。我可以调用 R 语言并使用它,但是我希望有一个纯 .Net 解决方案可以扩展到这些大型集合。

有什么建议么?

编辑#1:

我暂时已经使用 R 解决了。通过使用 statconn(在此处下载),我发现使用此方法既快速又相对容易。即这里是一个小代码片段,使用 R statconn 库的代码并不多(注意:这不是全部代码!)。

_StatConn.EvaluateNoReturn(string.Format("output <- lm({0})", equation));
object intercept = _StatConn.Evaluate("coefficients(output)['(Intercept)']");
parameters[0] = (double)intercept;
for (int i = 0; i < xColCount; i++)
{
  object parameter = _StatConn.Evaluate(string.Format("coefficients(output)['x{0}']", i));
  parameters[i + 1] = (double)parameter;
}
4

6 回答 6

3

作为记录,我最近发现了ALGLIB库,虽然没有太多文档,但它具有一些非常有用的功能,例如线性回归,这是我所追求的东西之一。

示例代码(这是旧的且未经验证的,只是我如何使用它的一个基本示例)。我在时间序列上使用线性回归,有 3 个条目(称为 3min/2min/1min),然后是完成值(Final)。

public void Foo(List<Sample> samples)
{
  int nAttributes = 3; // 3min, 2min, 1min
  int nSamples = samples.Count;
  double[,] tsData = new double[nSamples, nAttributes];
  double[] resultData = new double[nSamples];

  for (int i = 0; i < samples.Count; i++)
  {
    tsData[i, 0] = samples[i].Tminus1min;
    tsData[i, 1] = samples[i].Tminus2min;
    tsData[i, 2] = samples[i].Tminus3min;

    resultData[i] = samples[i].Final;
  }

  double[] weights = null;
  int fitResult = 0;
  alglib.lsfit.lsfitreport rep = new alglib.lsfit.lsfitreport();
  alglib.lsfit.lsfitlinear(resultData, tsData, nSamples, nAttributes, ref fitResult, ref weights, rep);

  Dictionary<string, double> labelsAndWeights = new Dictionary<string, double>();
  labelsAndWeights.Add("1min", weights[0]);
  labelsAndWeights.Add("2min", weights[1]);
  labelsAndWeights.Add("3min", weights[2]);
}
于 2010-10-19T22:51:14.970 回答
2

被反转的矩阵的大小不会随着联立方程(样本)的数量而增长。x.Transpose() * x 是一个方阵,其中维度是自变量的数量。

于 2010-05-26T10:12:28.580 回答
1

尝试Meta.Numerics

Meta.Numerics 是 .NET Framework 中用于高级科学计算的库。它可用于 C#、Visual Basic、F# 或任何其他 .NET 编程语言。Meta.Numerics 库完全面向对象,并针对实施和执行速度进行了优化。

要填充矩阵,请参阅ColumnVector Constructor (IList<Double>). 它可以ColumnVector从许多有序的实数集合中构造一个,包括 double[] 和 List。

于 2010-05-26T06:24:13.193 回答
1

我可以建议使用FinMath。它是极其优化的 .net 数值计算库。它使用英特尔数学核心函数库来执行复杂的计算,例如线性回归或矩阵求逆,但大多数类都有非常简单易用的接口。当然,它可以扩展到大量数据。mrnye 的示例将如下所示:

using FinMath.LeastSquares;
using FinMath.LinearAlgebra;

Vector y = new Vector(new double[]{745,
    895,
    442,
    440,
    1598});

Matrix X = new Matrix(new double[,]{
    {1, 36, 66},
    {1, 37, 68},
    {1, 47, 64},
    {1, 32, 53},
    {1, 1, 101}});

Vector b = OrdinaryLS.FitOLS(X, y);

Console.WriteLine(b);
于 2011-10-20T18:20:38.433 回答
1

为了进行线性回归,我倾向于使用Math.Net Numerics。

Math.NET Numerics 旨在为科学、工程和日常使用中的数值计算提供方法和算法。涵盖的主题包括特殊函数、线性代数、概率模型、随机数、插值、积分、回归、优化问题等。

例如,如果您想使用线性回归将数据拟合到一条直线上,就这么简单:

double[] xdata = new double[] { 10, 20, 30 };
double[] ydata = new double[] { 15, 20, 25 };
Tuple"<"double, double">" p = Fit.Line(xdata, ydata);
double a = p.Item1; // == 10; intercept
double b = p.Item2; // == 0.5; slope
于 2018-03-21T11:21:57.920 回答
0

我最近遇到了MathNet-Numerics——它在 MIT 许可下可用。

它声称为通用(X.Transpose() * X).Inverse() * (X.Transpose() * y)过程提供更快的替代方案。

这是本文的一些优化。第一个是:

X.TransposeThisAndMultiply(X).Inverse() * X.TransposeThisAndMultiply(y)

或者,您可以使用Cholesky 分解

X.TransposeThisAndMultiply(X).Cholesky().Solve(X.TransposeThisAndMultiply(y))
于 2017-09-22T05:52:54.520 回答