如何:求解器基础二次最小二乘法

时间:2011-11-18 19:54:23

标签: c# quadratic ms-solver-foundation

我有两个自变量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 Foundation中设置这个问题。非常感谢所有代码建议。

由于

3 个答案:

答案 0 :(得分:2)

我猜你不需要求解器基础。在数值优化中没有必要,因为解决方案(多项式系数的向量最小化了数据集中观察到的响应与预测响应之间的垂直距离的平方和)以封闭形式存在。

有关详细信息,请参阅wikipedia

答案 1 :(得分:1)

以下解决方案非常简单,只是尝试使用您描述的算法找到局部最小值。使用它我得到以下值

a = 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;
    }

答案 2 :(得分:0)

您可以使用求解器基础。您的回归已经是非线性的,实际上是generalized linear regression。在R中,您可以使用glm之类的包进行回归。

在C#中,我不确定是否存在任何开源代码。但无论如何,你可以自己解决优化问题,MSF中有一个非线性求解器!所以只写两个函数:

  1. 目标函数和

  2. 其渐变

  3. 作为一个简单的例子,你可以看到我的文章:

    Logistic Regression in F# using Microsoft Solver Foundation

    但是你不需要知道逻辑回归,在文章中,我还包括一个更简单的例子,展示了如何优化2变量Rosenbrock函数。

    MSF还使用其隐式转换语言功能为C#提供嵌入式域特定语言。 [你可以在MSF的文件中找到这个例子。]