我正在尝试实现一种将一条线拟合到一组 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/