如何:使用求解器基础的二次最小二乘问题

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 Foundation中设置此问题。非常感谢提供任何代码建议。

谢谢


我理解的是:您有一个 f(gls, gsh) ~= prob 的模型,并且想要优化模型函数的参数,对吗? - Efrain
将这篇庞大的理论论文转化为函数,可以通过微分得到精确的结果。 - Daniel
3个回答

2
我猜你不需要求解器基础知识。没有必要进行数值优化,因为解(多项式系数向量,最小化数据集中观测响应和预测响应之间的平方垂直距离之和)存在一个封闭形式。
详见wikipedia

1
嗨,这对解决我的问题非常有帮助(我现在已经用它解决了,非常感谢),但是我也希望学习如何使用Solver Foundation。 - user1054524

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

好的回答!我发现了一个小错别字(已经更正):var p = aMath.Pow(gls[i], 2) + bMath.Pow(gsh[i], 2) + cgls[i] + dgsh[i] + e; - Hannish

0

您可以使用Solver Foundation。您的回归已经是非线性的,实际上是广义线性回归。在R中,您可以使用像glm这样的软件包进行回归。

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

  1. 目标函数和

  2. 它的梯度

作为一个快速示例,您可以查看我的文章:

使用Microsoft Solver Foundation在F#中进行逻辑回归

但您不需要了解逻辑回归,在文章中,我还包括了一个更简单的示例,展示如何优化一个二元Rosenbrock函数。

MSF还具有嵌入式领域特定语言,可使用其隐式转换语言功能在C#中使用。[您可以在MSF的文档中找到示例。]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接