2010-05-26 71 views
15

Có ai biết cách hiệu quả để thực hiện hồi quy tuyến tính nhiều trong C#, trong đó số phương trình đồng thời có thể trong 1000 (với 3 hoặc 4 đầu vào khác nhau). Sau khi đọc this article trên hồi quy tuyến tính nhiều tôi đã cố gắng thực hiện nó với một phương trình ma trận:Hồi quy tuyến tính đa hiệu quả trong C#/.Net

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

Tuy nhiên nó cũng không quy mô với quy mô của năm 1000 của phương trình do các hoạt động ma trận nghịch đảo. Tôi có thể gọi ngôn ngữ R và sử dụng ngôn ngữ đó, tuy nhiên tôi hy vọng sẽ có một giải pháp thuần túy .Net sẽ mở rộng quy mô cho những tập hợp lớn này.

Mọi đề xuất?

EDIT # 1:

tôi đã giải quyết bằng R trong thời gian này. Bằng cách sử dụng statconn (tải về here) Tôi đã tìm thấy nó là cả hai nhanh chóng & tương đối dễ sử dụng phương pháp này. I E. đây là một đoạn mã nhỏ, nó thực sự không phải là nhiều mã ở tất cả để sử dụng thư viện R statconn (lưu ý: đây không phải là tất cả các mã!).

_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; 
} 
+0

sử dụng một thư viện GPU có lẽ? –

+0

Bạn có nghĩa là để làm cho các hoạt động ma trận chạy nhanh hơn? Tôi không nghĩ rằng đó sẽ là cách tiếp cận tốt nhất, tôi nghĩ cách tiếp cận tốt nhất sẽ là sử dụng một cách tiếp cận không theo kiểu ma trận (hoặc cái gì đó tránh được nghịch đảo). – mike

+0

Tôi đã thành công với http://www.codeproject.com/KB/recipes/LinReg.aspx Rất dễ sử dụng và nguồn mở! – BoroDrummer

Trả lời

3

Để ghi lại, gần đây tôi đã tìm thấy thư viện ALGLIB, trong khi không có nhiều tài liệu, có một số chức năng rất hữu ích như linear regression, một trong những điều tôi đã làm sau.

Mã mẫu (mã này cũ và chưa được xác minh, chỉ là một ví dụ cơ bản về cách tôi đang sử dụng nó). Tôi đã sử dụng hồi quy tuyến tính trên chuỗi thời gian với 3 mục (gọi là 3min/2min/1min) và sau đó là giá trị hoàn thành (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]); 
} 
+0

Đề xuất hay. Bất kỳ ví dụ mã nào bạn sẵn sàng đăng? – Mario

+0

Xem chỉnh sửa cho một số mã mẫu, tôi hy vọng nó vẫn hoạt động (bạn sẽ cần một tham chiếu đến alglib) – mike

+0

Tốt. Làm thế nào bạn sẽ kết hợp một biến không đổi không xác định vào mẫu này? – Oriental

1

Hãy thử Meta.Numerics:

Meta.Numerics là một thư viện cho tính toán khoa học tiên tiến trong .NET Framework. Nó có thể được sử dụng từ C#, Visual Basic, F # hoặc bất kỳ ngôn ngữ lập trình .NET nào khác. Thư viện Meta.Numerics hoàn toàn hướng đối tượng và được tối ưu hóa cho tốc độ triển khai và thực thi.

Để điền ma trận, hãy xem ví dụ về ColumnVector Constructor (IList<Double>). Nó có thể xây dựng một ColumnVector từ nhiều bộ sưu tập theo thứ tự của thực tế, bao gồm double [] và List.

+0

Cảm ơn, tôi chưa từng thấy thư viện đó trước đây. Có vẻ tốt, nhưng vẫn bị các vấn đề tương tự giải quyết các phương trình với ma trận. Tôi nghĩ tôi cần một cách tiếp cận khác. – mike

2

Kích thước của ma trận bị đảo ngược KHÔNG phát triển với số phương trình đồng thời (mẫu). x.Transpose() * x là một ma trận vuông nơi thứ nguyên là số biến độc lập.

+0

Điểm thú vị, tôi tự hỏi tại sao hiệu suất của tôi lại giảm xuống quá nhiều? Tôi có khoảng 6000 mẫu trong bộ của tôi. Tôi sẽ phải điều tra thêm điều này. – mike

+0

Tôi đoán hiệu suất của bạn sẽ giảm vì x.Transpose() * x mất nhiều thời gian hơn với các ma trận lớn hơn. Tôi có một thư viện ở đâu đó hoạt động cho hàng triệu điểm dữ liệu ... Tôi sẽ cố gắng đào nó lên nếu bạn quan tâm. Tôi phải đối mặt với vấn đề này khoảng hai mươi năm trước (có tôi cũ) và tìm thấy một giải pháp toán học thông minh :-) –

+1

Bạn nên sử dụng phương pháp gradient gốc nếu bạn muốn mở rộng quy mô tốt hơn. –

1

Tôi có thể đề nghị sử dụng FinMath. Nó là thư viện tính toán số .net cực kỳ được tối ưu hóa. Nó sử dụng Thư viện hạt nhân toán học của Intel để thực hiện các phép tính phức tạp như hồi quy tuyến tính hoặc nghịch đảo ma trận, nhưng hầu hết các lớp đều có các giao diện rất dễ tiếp cận. Và tất nhiên, nó có thể mở rộng thành một tập hợp lớn dữ liệu. Ví dụ mrnye sẽ là như thế này:

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); 
0

Gần đây tôi đi qua MathNet-Numerics - mà được phát hành theo giấy phép MIT.

Xác nhận quyền sở hữu cung cấp giải pháp thay thế nhanh hơn cho quy trình phổ biến (X.Transpose() * X).Inverse() * (X.Transpose() * y).

Dưới đây là một số tối ưu hóa từ this article. Đầu tiên là một con người:

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

Hoặc, bạn có thể sử dụng Cholesky decomposition:

Các vấn đề liên quan