2011-10-17 8 views
22

में गैर रेखीय प्रतिगमन पूर्वानुमानित उद्देश्यों के लिए, 2 डी डेटा सेट के आधार पर, मैं एक गैर-रैखिक (अधिमानतः वर्गबद्ध) वक्र उत्पन्न करने का एक तरीका ढूंढ रहा हूं। अभी मैं एक रैखिक प्रवृत्ति का उत्पादन करने के लिए सामान्य कम से कम वर्ग (ओएलएस) के अपने कार्यान्वयन का उपयोग कर रहा हूं, लेकिन मेरे रुझान एक वक्र मॉडल के लिए अधिक उपयुक्त हैं। जिस डेटा का मैं विश्लेषण कर रहा हूं वह समय के साथ सिस्टम लोड है।सी #

यहाँ समीकरण है कि मैं अपने रैखिक गुणांक उत्पादन करने के लिए उपयोग कर रहा हूँ है:

Ordinary Least Squares (OLS) formula

मैं Math.NET संख्यात्मक और कुछ अन्य libs पर एक नज़र लिया है, लेकिन वे या तो प्रक्षेप प्रदानप्रतिशोध (जो मेरे लिए कोई उपयोग नहीं है) के बजाय, या कोड किसी भी तरह से काम नहीं करता है।

किसी को भी किसी भी मुक्त ओपन सोर्स libs या कोड नमूने के बारे में पता है जो ऐसे वक्र के लिए गुणांक उत्पन्न कर सकते हैं?

+0

यह वही परिणाम है जो मैं देख रहा हूं: http://www3.wolframalpha.com/input/?i=quadratic+fit+%7B1%2C82.96%7D%2C%7B2%2C86.23%7D % 2C% 7B3% 2C87.09% 7 दिन% 2C% 7B4% 2C84.28% 7 दिन% 2C% 7B5% 2C83.69% 7 दिन% 2C% 7B6% 2C89.18% 7 दिन% 2C% 7B7% 2C85.71% 7 दिन % 2C% 7B8% 2C85.05% 7 दिन% 2C% 7B9% 2C85.58% 7 दिन% 2C% 7B10% 2C86.95% 7 दिन% 2C% 7B11% 2C87.95% 7 दिन% 2C% 7B12% 2C89.44% 7 दिन % 2 सी% 7 बी 13% 2C93.47% 7 डी – Polynomial

+0

लिंक के साथ एक और क्यू: http://stackoverflow.com/questions/882009/is-there-any-tool-for-regression-model एक प्रासंगिक दिखने वाला कोडप्रोजेक्ट चीज़: http: //www.codeproject.com/KB/recipes/QuadraticRegression.aspx – AakashM

+0

पूर्व इंटरपोलेशन मॉडल के लिंक का एक सेट है, और बाद में असामान्य रूप से गलत/निर्विवाद परिणाम देता है, इसे 'डबल' के बजाय 'दशमलव' का उपयोग करने के बाद भी परिवर्तित किया जाता है '। – Polynomial

उत्तर

24

मैं MathNet.Iridium रिहाई का इस्तेमाल किया है क्योंकि यह .NET 3.5 और VS2008 साथ संगत है। विधि Vandermonde मैट्रिक्स पर आधारित है। [1,0.57,-0.15] की

using MathNet.Numerics.LinearAlgebra; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Vector x_data = new Vector(new double[] { 0, 1, 2, 3, 4 }); 
     Vector y_data = new Vector(new double[] { 1.0, 1.4, 1.6, 1.3, 0.9 }); 

     var poly = new PolynomialRegression(x_data, y_data, 2); 

     Console.WriteLine("{0,6}{1,9}", "x", "y"); 
     for (int i = 0; i < 10; i++) 
     { 
      double x = (i * 0.5); 
      double y = poly.Fit(x); 

      Console.WriteLine("{0,6:F2}{1,9:F4}", x, y); 
     } 
    } 
} 

परिकलित गुणांक उत्पादन के साथ:

x  y 
0.00 1.0000 
0.50 1.2475 
1.00 1.4200 
1.50 1.5175 
2.00 1.5400 
2.50 1.4875 
3.00 1.3600 
3.50 1.1575 
4.00 0.8800 
4.50 0.5275 

कौन से मेल खाता है तब मैं अपने बहुपद प्रतिगमन धारण करने के लिए

using MathNet.Numerics.LinearAlgebra; 

public class PolynomialRegression 
{ 
    Vector x_data, y_data, coef; 
    int order; 

    public PolynomialRegression(Vector x_data, Vector y_data, int order) 
    { 
     if (x_data.Length != y_data.Length) 
     { 
      throw new IndexOutOfRangeException(); 
     } 
     this.x_data = x_data; 
     this.y_data = y_data; 
     this.order = order; 
     int N = x_data.Length; 
     Matrix A = new Matrix(N, order + 1); 
     for (int i = 0; i < N; i++) 
     { 
      A.SetRowVector(VandermondeRow(x_data[i]) , i); 
     } 

     // Least Squares of |y=A(x)*c| 
     // tr(A)*y = tr(A)*A*c 
     // inv(tr(A)*A)*tr(A)*y = c 
     Matrix At = Matrix.Transpose(A); 
     Matrix y2 = new Matrix(y_data, N); 
     coef = (At * A).Solve(At * y2).GetColumnVector(0); 
    } 

    Vector VandermondeRow(double x) 
    { 
     double[] row = new double[order + 1]; 
     for (int i = 0; i <= order; i++) 
     { 
      row[i] = Math.Pow(x, i); 
     } 
     return new Vector(row); 
    } 

    public double Fit(double x) 
    { 
     return Vector.ScalarProduct(VandermondeRow(x) , coef); 
    } 

    public int Order { get { return order; } } 
    public Vector Coefficients { get { return coef; } } 
    public Vector XData { get { return x_data; } } 
    public Vector YData { get { return y_data; } } 
} 

जो तब मैं इसे इस तरह का प्रयोग कर एक श्रेणी का निर्माण वोल्फ्राम अल्फा से quadratic परिणाम। Quadratic Equation Quadratic Fit

संपादित करें 1 फिट आप x_data और y_data निम्नलिखित आरंभ की कोशिश करना चाहते हैं पाने के लिए:

Matrix points = new Matrix(new double[,] { { 1, 82.96 }, 
       { 2, 86.23 }, { 3, 87.09 }, { 4, 84.28 }, 
       { 5, 83.69 }, { 6, 89.18 }, { 7, 85.71 }, 
       { 8, 85.05 }, { 9, 85.58 }, { 10, 86.95 }, 
       { 11, 87.95 }, { 12, 89.44 }, { 13, 93.47 } }); 
Vector x_data = points.GetColumnVector(0); 
Vector y_data = points.GetColumnVector(1); 

जो निम्नलिखित गुणांक (सबसे कम बिजली से उच्चतम करने के लिए) का उत्पादन

Coef=[85.892,-0.5542,0.074990] 
    x  y 
    0.00 85.8920 
    1.00 85.4127 
    2.00 85.0835 
    3.00 84.9043 
    4.00 84.8750 
    5.00 84.9957 
    6.00 85.2664 
    7.00 85.6871 
    8.00 86.2577 
    9.00 86.9783 
10.00 87.8490 
11.00 88.8695 
12.00 90.0401 
13.00 91.3607 
14.00 92.8312 
+0

मेरी समस्या को पूरी तरह हल किया। धन्यवाद :) – Polynomial

+3

मैंने आपके उत्तर को अनुकूलित और अपग्रेड किया :) http://stackoverflow.com/a/12770686/1046374 –

0

मैं इसे कैसे किया जा सकता है इसके बारे में एक विचार प्राप्त करने के लिए http://mathforum.org/library/drmath/view/53796.html पर एक नज़र डालेंगे।

फिर this का एक अच्छा कार्यान्वयन है जो मुझे लगता है कि आपकी मदद करेगा।

+0

वह कार्यान्वयन मेरे लिए काम नहीं करता था। इसने बॉक्स के बाहर पूरी तरह से गलत परिणाम (coeffs के लिए 0/1/0) दिए और कुछ tweaking अभी भी पूरी तरह से निर्दोष था। मैंने पहले खोजे वोल्फ्राम अल्फा परिणामों की तरह कुछ भी नहीं। आपके द्वारा प्रदान किए गए लिंक में गणित मुझसे परे है, दुर्भाग्य से। – Polynomial

6

मुझे नहीं लगता कि आप गैर रेखीय प्रतिगमन चाहते हैं। भले ही आप एक वर्गबद्ध कार्य का उपयोग कर रहे हों, फिर भी इसे रैखिक प्रतिगमन कहा जाता है। आप जो चाहते हैं उसे बहुविकल्पीय प्रतिगमन कहा जाता है। यदि आप एक वर्गबद्ध चाहते हैं तो आप अपने आश्रित चर में एक एक्स वर्ग अवधि जोड़ें।

+0

रैखिक प्रतिगमन मुझे एक रेखा देता है। मुझे नहीं पता कि मैंने कुछ समीकरण करने के लिए पोस्ट किए गए समीकरण को कैसे संपादित किया है। मैं इस तरह का परिणाम प्राप्त करना चाहता हूं: http://www3.wolframalpha.com/input/?i=quadratic+fit+%7B1%2C82.96%7D%2C%7B2%2C86.23%7D%2C%7B3% 2C87.09% 7 दिन% 2C% 7B4% 2C84.28% 7 दिन% 2C% 7B5% 2C83.69% 7 दिन% 2C% 7B6% 2C89.18% 7 दिन% 2C% 7B7% 2C85.71% 7 दिन% 2C% 7B8% 2C85.05% 7 दिन% 2C% 7B9% 2C85.58% 7 दिन% 2C% 7B10% 2C86.95% 7 दिन% 2C% 7B11% 2C87.95% 7 दिन% 2C% 7B12% 2C89.44% 7 दिन% 2C% 7B13% 2C93.47% 7 डी – Polynomial

+0

http://luna.cas.usf.edu/~mbrannic/files/regression/Reg2IV.html – Tim

+0

देखें सूत्र का उपयोग करें। लेकिन x1 x2 के बजाय आपके एक्स और एक्स वर्ग का उपयोग करें। यदि आपको अभी भी समस्याएं हैं तो मैं एक्सेल या स्यूडोकोड में एक उदाहरण कैल्क की कोशिश करूंगा। – Tim

7

@ ja72 कोड बहुत अच्छा है। लेकिन मैंने इसे Math.NET के वर्तमान संस्करण पर पोर्ट किया (मैथनेट.इरिडियम अब मुझे समझ में नहीं आता है) और कोड आकार और प्रदर्शन दोनों को अनुकूलित करें (धीमे प्रदर्शन के कारण Math.Pow फ़ंक्शन मेरे सॉल्चरेशन में उपयोग नहीं कर रहा है)।

public class PolynomialRegression 
{ 
    private int _order; 
    private Vector<double> _coefs; 

    public PolynomialRegression(DenseVector xData, DenseVector yData, int order) 
    { 
     _order = order; 
     int n = xData.Count; 

     var vandMatrix = new DenseMatrix(xData.Count, order + 1); 
     for (int i = 0; i < n; i++) 
      vandMatrix.SetRow(i, VandermondeRow(xData[i])); 

     // var vandMatrixT = vandMatrix.Transpose(); 
     // 1 variant: 
     //_coefs = (vandMatrixT * vandMatrix).Inverse() * vandMatrixT * yData; 
     // 2 variant: 
     //_coefs = (vandMatrixT * vandMatrix).LU().Solve(vandMatrixT * yData); 
     // 3 variant (most fast I think. Possible LU decomposion also can be replaced with one triangular matrix): 
     _coefs = vandMatrix.TransposeThisAndMultiply(vandMatrix).LU().Solve(TransposeAndMult(vandMatrix, yData)); 
    } 

    private Vector<double> VandermondeRow(double x) 
    { 
     double[] result = new double[_order + 1]; 
     double mult = 1; 
     for (int i = 0; i <= _order; i++) 
     { 
      result[i] = mult; 
      mult *= x; 
     } 
     return new DenseVector(result); 
    } 

    private static DenseVector TransposeAndMult(Matrix m, Vector v) 
    { 
     var result = new DenseVector(m.ColumnCount); 
     for (int j = 0; j < m.RowCount; j++) 
      for (int i = 0; i < m.ColumnCount; i++) 
       result[i] += m[j, i] * v[j]; 
     return result; 
    } 

    public double Calculate(double x) 
    { 
     return VandermondeRow(x) * _coefs; 
    } 
} 

यह github:gist पर भी उपलब्ध है।