如果它有助于这是我用于这种事情的C代码。它对疯狂的物理学家说的很少。
首先关闭,公式。如果通过某些点拟合y ^:x-> a * x + b线,则错误给出:
E = Sum{ sqr(y[i]-y^(x[i])) }/ N = Vy - Cxy*Cxy/Vx
where
Vx is the variance of the xs
Vy that of the ys
Cxy the covariance of the as and the ys
下面的代码使用包含均值,差异,协方差和计数的结构。
函数moms_acc_pt()添加新点时更新这些。函数moms_line()返回该行的A和B,以及如上所述的错误。返回的fmax(0,)是在近乎完美的符合胜度的情况下,舍入错误可以发送(数学上非负)结果负。
虽然可以具有从瞬间删除一个点的函数,但我发现决定通过乘坐副本来添加一个点,累积副本中的点,恢复副本中的点,恢复副本的函数更容易处理。保持副本的副本是最适合的点,以及其他
的原件
typedef struct
{ int n; // number points
double xbar,ybar; // means of x,y
double Vx, Vy; // variances of x,y
double Cxy; // covariance of x,y
} momentsT;
// update the moments to include the point x,y
void moms_acc_pt( momentsT* M, double x, double y)
{ M->n += 1;
double f = 1.0/M->n;
double dx = x-M->xbar;
double dy = y-M->ybar;
M->xbar += f*dx;
M->ybar += f*dy;
double g = 1.0 - f;
M->Vx = g*(M->Vx + f*dx*dx);
M->Cxy = g*(M->Cxy + f*dx*dy);
M->Vy = g*(M->Vy + f*dy*dy);
}
// return the moments for the combination of A and B (assumed disjoint)
momentsT moms_combine( const momentsT* A, const momentsT* B)
{
momentsT C;
C.n = A->n + B->n;
double alpha = (double)A->n/(double)C.n;
double beta = (double)B->n/(double)C.n;
C.xbar = alpha*A->xbar + beta*B->xbar;
C.ybar = alpha*A->ybar + beta*B->ybar;
double dx = A->xbar - B->xbar;
double dy = A->ybar - B->ybar;
C.Vx = alpha*A->Vx + beta*B->Vx + alpha*beta*dx*dx;
C.Cxy= alpha*A->Cxy+ beta*B->Cxy+ alpha*beta*dx*dy;
C.Vy = alpha*A->Vy + beta*B->Vy + alpha*beta*dy*dy;
return C;
}
// line is y^ : x -> a*x + b; return Sum{ sqr( y[i] - y^(x[i])) }/N
double moms_line( momentsT* M, double* a, double *b)
{ *a = M->Cxy/M->Vx;
*b = M->ybar - *a*M->xbar;
return fmax( 0.0, M->Vy - *a*M->Cxy);
}