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

谢谢

4

3 回答 3

2

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

有关详细信息,请参阅维基百科

于 2011-11-23T04:35:18.630 回答
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;
    }
于 2011-11-23T19:58:44.790 回答
0

您可以使用求解器基础。您的回归已经是非线性的,实际上是广义线性回归。在 R 中,您可以使用 package likeglm进行回归。

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

  1. 目标函数和

  2. 它的梯度

举个简单的例子,你可以看看我的文章:

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

但是您不需要了解逻辑回归,在本文中,我还包含了一个更简单的示例,展示了如何优化 2 变量 Rosenbrock 函数。

MSF 还使用其隐式转换语言特性为 C# 嵌入了特定于域的语言。[你可以在 MSF 的文档中找到这个例子。]

于 2011-11-23T04:44:44.143 回答