Эффективная множественная линейная регрессия в С#/.Net

Кто-нибудь знает об эффективном способе выполнения множественной линейной регрессии в С#, где число одновременных уравнений может быть в 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;
}

Ответы

Ответ 1

Для записи я недавно нашел библиотеку ALGLIB, которая, не имея большой документации, имеет некоторые очень полезные функции, такие как линейная регрессия, которая является одной из вещей, которые я был после.

Пример кода (это старый и непроверенный, просто базовый пример того, как я его использовал). Я использовал линейную регрессию во временных рядах с 3 записями (называемый 3мин/2мин/1 мин), а затем финишным значением (Финал).

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]);
}

Ответ 2

Размер инвертируемой матрицы НЕ растет с количеством одновременных уравнений (выборок).   x.Transpose() * x - квадратная матрица, где размерность - это число независимых переменных.

Ответ 3

Попробуйте Meta.Numerics:

Meta.Numerics - это библиотека для продвинутых научных вычислений в .NET Framework. Он может использоваться с С#, Visual Basic, F # или любым другим языком программирования .NET. Библиотека Meta.Numerics полностью объектно-ориентирована и оптимизирована для скорости выполнения и выполнения.

Чтобы заполнить матрицу, см. пример ColumnVector Constructor (IList<Double>). Он может построить ColumnVector из множества упорядоченных наборов реалов, включая double [] и List.

Ответ 4

Я могу предложить использовать FinMath. Это чрезвычайно оптимизированная вычислительная библиотека .net.net. Он использует библиотеку ядра Intel Math для выполнения сложных вычислений, таких как линейная регрессия или обратная матрица, но большинство классов имеют очень простые доступные интерфейсы. И, конечно же, он масштабируется для больших наборов данных. Пример 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);

Ответ 5

Недавно я встретил 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))