2011-11-18 100 views
6

我有兩個獨立變量,GSHGls。使用這兩個變量,我試圖預測結果,prob。使用表格的函數:如何:求解基礎二次最小二乘法

prob=a*Gls^2+b*GSH^2+c*Gls+d*GSH+e // (where a,b,c,d,e are coefficients) 

數據的樣本:

Gls(2.3 2.3 2.5 2.5 2.5 2.5 2.7 2.7 2.7 2.7 2.7 2.9 2.9 2.9 2.9 2.9 3.1 3.1 3.1 3.1 3.1 3.1 3.3 3.3 3.3 3.3 3.3 3.3 3.5 3.5 3.5 3.5 3.5) 

GSH(0.475 0.525 0.425 0.475 0.525 0.575 0.425 0.475 0.525 0.575 0.625 0.425 0.475 0.525 0.575 0.625 0.375 0.425 0.475 0.525 0.575 0.625 0.375 0.425 0.475 0.525 0.575 0.625 0.425 0.475 0.525 0.575 0.625) 

prob(0.263636 0.324159 0.319328 0.291295 0.286086 0.253994 0.233766 0.284644 0.273818 0.263743 0.175182 0.243986 0.284848 0.28066 0.247863 0.183468 0.181818 0.237288 0.269266 0.2555 0.240924 0.206081 0.209677 0.216949 0.263261 0.25966 0.23588 0.203252 0.239316 0.209184 0.234818 0.242424 0.192118) 

我想找到係數的最佳值,以儘量減少最小二乘法的總和。

我已經在基礎求解中讀了很多,但是我一直無法解決如何在c#Solver基礎中設置這個問題。所有的代碼建議非常感謝。

謝謝

+0

我是否明白這一點:你有f(gls,gsh)〜= prob,你想優化模型函數的參數嗎? – Efrain

+0

在一張巨大的theoritac紙上使用這個哦可以給出一個使用差異的確切結果。嘗試將該紙張轉換爲函數 – Dani

回答

2

我想你不需要求解器基礎。在數值優化中不需要,因爲解決方案(使數據集中的觀測響應與預測響應之間的垂直距離的平方之和最小化的多項式係數的向量)以閉合形式存在。

查看wikipedia瞭解詳情。

+1

嗨,這對於解決這個問題非常有用(我現在已經完成了這個工作,非常感謝),但是我也希望學習如何使用解算器基礎。 – user1054524

0

您可以使用求解器基礎。你的迴歸已經是非線性的,實際上是一個generalized linear regression。在R中,您可以使用像glm這樣的包進行迴歸。

在C#中,我不確定是否存在任何開放源代碼。但無論如何,你可以自己解決優化問題,而MSF有一個非線性求解器!所以只寫了兩個功能:

  1. 的目標函數和

  2. 及其梯度

作爲一個簡單的例子,你可以看到我的文章:

Logistic Regression in F# using Microsoft Solver Foundation

但是你不需要知道邏輯迴歸,在文章中,我還包含一個簡單的例子,展示如何優化雙變量Rosenbrock函數。

MSF還使用其隱式轉換語言功能爲C#提供了嵌入式域特定語言。 [你可以在MSF的文檔中找到這個例子。]

1

下面的解決方案非常簡單,只是試圖用你描述的算法找到局部最小值。使用它,我得到以下值

一個= 0.02527237,B = 0.04768372,C = -0.001549721,d = 0.01382828,E = 0.002026558

與0.2139592總平方。

static void Main(string[] args) 
    { 
     var a = FindLocalMinimum(x => SumSq(x, 0, 0, 0, 0)); 
     var b = FindLocalMinimum(x => SumSq(a, x, 0, 0, 0)); 
     var c = FindLocalMinimum(x => SumSq(a, b, x, 0, 0)); 
     var d = FindLocalMinimum(x => SumSq(a, b, c, x, 0)); 
     var e = FindLocalMinimum(x => SumSq(a, b, c, d, x)); 
    } 

    private static float SumSq(float a, float b, float c, float d, float e) 
    { 
     var gls = new[] 
         { 
          2.3, 2.3, 2.5, 2.5, 2.5, 2.5, 2.7, 2.7, 2.7, 2.7, 2.7, 2.9, 2.9, 2.9, 2.9, 2.9, 3.1, 3.1, 3.1 
          , 3.1, 3.1, 3.1, 3.3, 3.3, 3.3, 3.3, 3.3, 3.3, 3.5, 3.5, 3.5, 3.5, 3.5 
         }; 

     var gsh = new[] 
         { 
          0.475, 0.525, 0.425, 0.475, 0.525, 0.575, 0.425, 0.475, 0.525, 0.575, 0.625, 0.425, 0.475, 
          0.525, 0.575, 0.625, 0.375, 0.425, 0.475, 0.525, 0.575, 0.625, 0.375, 0.425, 0.475, 0.525, 
          0.575, 0.625, 0.425, 0.475, 0.525, 0.575, 0.625 
         }; 

     var prob = new[] 
         { 
          0.263636, 0.324159, 0.319328, 0.291295, 0.286086, 0.253994, 0.233766, 0.284644, 0.273818, 
          0.263743, 0.175182, 0.243986, 0.284848, 0.28066, 0.247863, 0.183468, 0.181818, 0.237288, 
          0.269266, 0.2555, 0.240924, 0.206081, 0.209677, 0.216949, 0.263261, 0.25966, 0.23588, 
          0.203252, 0.239316, 0.209184, 0.234818, 0.242424, 0.192118 
         }; 

     var res = 0.0; 
     for (var i = 0; i < prob.Length; i++) 
     { 
      var p = a*Math.Pow(gls[i], 2) + a*Math.Pow(gsh[i], 2) + c*gls[i] + d*gsh[i] + e; 
      res += Math.Pow(p - prob[i], 2); 
     } 
     return (float)res; 
    } 

    private static float FindLocalMinimum(Func<float, float> f) 
    { 
     float bestV = float.MaxValue; 
     float bestX = 0; 
     float x = 0; 
     float lastV = bestV; 
     float diff = 1000.0f; 
     while (Math.Abs(diff) > 0.0001f) 
     { 
      float v = f(x); 
      if (v < bestV) 
      { 
       bestV = v; 
       bestX = x; 
      } 
      else if (v > lastV) 
      { 
       diff *= -0.5f; 
      } 
      lastV = v; 
      x += diff; 
     } 
     return bestX; 
    } 
+0

很好的答案!我發現了一個小的錯字(這裏更正了): var p = a * Math.Pow(gls [i],2)+ b * Math.Pow(gsh [i],2)+ c * gls [i] + d * gsh [i] + e; – Hannish