我正在尝试实现一种将一条线拟合到一组 2D 点的方法。
我编写了以下代码,从两个数组(X,Y 坐标)中读取数据
并应使用最小二乘法计算最佳拟合线的参数。
我使用了这里给出的公式:
mathworld.wolfram

- (void) linearRegressionOfUserAcceleration
{
     double avgX = [[_accelBufferX valueForKeyPath:@"@avg.doubleValue"] doubleValue];
     double avgY = [[_accelBufferY valueForKeyPath:@"@avg.doubleValue"] doubleValue];
     int n = _accelBufferX.count;

     double ssX, ssY, ssXY;
     ssX = ssY = ssXY = 0;
     int i;

     // Sum of squares X, Y & X*Y
     for (i = 0; i < n; i++)
     {
         ssX += pow([[_accelBufferX objectAtIndex:i] doubleValue],2);
         ssY += pow([[_accelBufferY objectAtIndex:i] doubleValue],2);
         ssXY += [[_accelBufferX objectAtIndex:i] doubleValue] * [[_accelBufferY objectAtIndex:i] doubleValue];
     }

     ssX = ssX - n * pow(avgX,2);
     ssY = ssY - n * pow(avgY,2);
     ssXY = ssXY - n * avgX * avgY;

     // Best fit of line y_i = a + b * x_i
     b = ssXY / ssX;
     a = avgY - b * avgX;

     // Correlationcoefficent gives the quality of the estimate: 1 = perfect to 0 = no fit
     corCoeff = pow(ssXY,2) / ssX * ssY;

     NSLog(@"n: %d, a: %f --- b: %f --- cor: %f --- avgX: %f --- avgY: %f --- ssX: %f - ssY: %f - ssXY: %f", n, a, b, corCoeff, avgX, avgY, ssX, ssY, ssXY);
}

我得到这样的输出:
  n: 15, a: -0.095204 --- b: 0.929245 --- cor: 3.567163   --- avgX: -0.017827 -- avgY: -0.111770 --- ssX: 2.176048 - ssY: 1.898429 - ssXY: 2.022081

结果线根本不适合数据,尽管 corelationCoefficient 有时大于 1,但恕我直言,如果一切正常,这种情况永远不会发生。

有人在我的实现中看到任何错误吗?

- 编辑 -

这是更正后的代码,遵循 CRD 的提示。
我用这个来提取采样的userAcceleration 在两步之间水平面的方向向量,得到步向。

这对我有用:
- (void) linearRegressionOfUserAcceleration
{
    NSUInteger n = _accelBufferX.count;
    double ax, ay, sX, sY, ssX, ssY, ssXY, avgX, avgY;

    // Sum of squares X, Y & X*Y
    for (NSUInteger i = 0; i < n; i++)
    {
        @synchronized(self) {
            ax = [[_accelBufferX objectAtIndex:i] doubleValue];
            ay = [[_accelBufferY objectAtIndex:i] doubleValue];
        }
        sX += ax;
        sY += ay;
        ssX += ax * ax;
        ssY += ay * ay;
        ssXY += ax * ay;
    }

    avgX = sX / n;
    avgY = sY / n;
    radius = hypot(avgX, avgY);
    ssX = ssX - n * (avgX * avgX);
    ssY = ssY - n * (avgY * avgY);
    ssXY = ssXY - n * avgX * avgY;

    // Best fit of line y_i = a + b * x_i
    b = ssXY / ssX;
    a = (avgY - b * avgX);
    theta = atan2(1, b);


    // Correlationcoefficent gives the quality of the estimate: 1 = perfect to 0 = no fit
    corCoeff = (ssXY * ssXY) / (ssX * ssY);

    NSLog(@"n: %d, a: %f --- b: %f --- cor: %f   --- avgX: %f -- avgY: %f --- ssX: %f - ssY: %f - ssXY: %f", n, a, b, corCoeff, avgX, avgY, ssX, ssY, ssXY);
}

最佳答案

输入一些您可以手动检查的已知数据,例如{1,1}、{2,2}、{3,3}。平均值是否正确?如果是这样,继续进行求和等。错误将显露出来。

在代码本身上,您可以通过删除对 @"avg.doubleValue"的调用并在单个循环中生成所有总和,使其更清晰,顺便说一句,效率更高:

// Sum of X, Y, X^2, Y^2 & X*Y
for (NSUInteger i = 0; i < n; i++)
{
   double x = [[_accelBufferX objectAtIndex:i] doubleValue];
   double y = [[_accelBufferY objectAtIndex:i] doubleValue];
   sX += x;
   sY += y;
   ssX += x * x;
   ssY += y * y;
   ssXY += x * y;
}

关于objective-c - Objective-C 中的线性回归,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10863732/

10-12 22:43