2011-11-18 99 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