Linear Regression in Objective-C

I am trying to implement a method that fits a row to a set of points in 2D. I wrote the following code that reads data from two arrays (X, Y coordinate) and must calculate the parameters of the best fitting line using the least squares method. I used the formulas given here: 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); } 

I get the following results:

  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 

The resulting row does not match the data at all, and although the correlation coefficient is sometimes greater than one, that IMHO should never happen if everything works correctly.

Does anyone see errors in my implementation?

- EDIT -

This is the corrected code following the prompt from CRD. I used this to extract the directional vector of the selective user acceleration in the horizontal plane between two steps to get the step direction.

This worked for me:

 - (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); } 
+4
source share
1 answer

Put some known data that you can check manually, for example. {1,1}, {2,2}, {3,3}. Are the average values โ€‹โ€‹correct? If it goes to the amounts, etc. The error will show itself.

In the code itself, you can make it more understandable and, by the way, more efficient by dropping calls to @ "avg.doubleValue" and producing all your amounts in one cycle:

 // 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; } 
+3
source

Source: https://habr.com/ru/post/1415731/


All Articles