用二阶二次曲线平滑小数据集

时间:2010-04-06 01:16:19

标签: c++ c statistics signal-processing quadratic

我正在进行一些特定的信号分析,我需要一种能够消除给定钟形分布曲线的方法。平均运行方法不能产生我想要的结果。我希望保持最小/最大,并保持拟合曲线的一般形状,但要解决采样中的不一致问题。

简而言之:如果给出一组模拟简单二次曲线的数据,您会推荐哪种统计平滑方法?

如果可能,请参考实施,库或框架。

非常感谢!

修改:一些有用的数据

(可能的信号图)

alt text http://i40.tinypic.com/b49942.png

深色二次曲线是浅色连接数据点的“拟合”曲线。

样本@ -44(大约),是我图中的一个问题(即潜在的样本不一致)。我需要这条曲线更好地“适应”分布,并克服不相应趋势的值。希望这有帮助!

4 个答案:

答案 0 :(得分:3)

“二次”曲线是一回事; “钟形”通常表示高斯正态分布。获得最佳估计高斯不容易:你计算样本均值和方差,你的平滑近似是

y = exp(-squared(x-mean)/variance)

另一方面,如果想要用四边形近似平滑曲线,我建议使用最小平方误差计算二次多项式。我可以记住这个公式,但是如果你有微积分,则写出总平方误差的公式(逐点)并相对于二次系数进行微分。将一阶导数设置为零并求解最佳近似值。或者你可以查一查。

最后,如果你只想要一个平滑的曲线来近似一组点,cubic splines是你最好的选择。曲线不一定意味着什么,但你会得到一个很好的平滑近似。

答案 1 :(得分:2)

#include <iostream>
#include <math.h>

struct WeightedData 
{
double x;
double y;
double weight;
};

void findQuadraticFactors(WeightedData *data, double &a, double &b, double &c, unsigned int const datasize)
{
double w1 = 0.0;
double wx = 0.0, wx2 = 0.0, wx3 = 0.0, wx4 = 0.0;
double wy = 0.0, wyx = 0.0, wyx2 = 0.0;
double tmpx, tmpy;
double den;

for (unsigned int i = 0; i < datasize; ++i) 
    {
    double x = data[i].x;
    double y = data[i].y;
    double w = data[i].weight;  

    w1 += w;
    tmpx = w * x;
    wx += tmpx;
    tmpx *= x;
    wx2 += tmpx;
    tmpx *= x;
    wx3 += tmpx;
    tmpx *= x;
    wx4 += tmpx;
    tmpy = w * y;
    wy += tmpy;
    tmpy *= x;
    wyx += tmpy;
    tmpy *= x;
    wyx2 += tmpy;
    }

den = wx2 * wx2 * wx2 - 2.0 * wx3 * wx2 * wx + wx4 * wx * wx + wx3 * wx3 * w1 - wx4 * wx2 * w1;
if (den == 0.0) 
    {
    a = 0.0;
    b = 0.0;
    c = 0.0;
    }
else    
    {
    a = (wx * wx * wyx2 - wx2 * w1 * wyx2 - wx2 * wx * wyx + wx3 * w1 * wyx + wx2 * wx2 * wy - wx3 * wx * wy) / den;
    b = (-wx2 * wx * wyx2 + wx3 * w1 * wyx2 + wx2 * wx2 * wyx - wx4 * w1 * wyx - wx3 * wx2 * wy + wx4 * wx * wy) / den;
    c = (wx2 * wx2 * wyx2 - wx3 * wx * wyx2 - wx3 * wx2 * wyx + wx4 * wx * wyx + wx3 * wx3 * wy - wx4 * wx2 * wy) / den;
    }

}

double findY(double const a, double const b, double const c, double const x)
{       
return a * x * x + b * x + c; 
};




int main(int argc, char* argv[])
{
WeightedData data[9];
data[0].weight=1; data[0].x=1; data[0].y=-52.0; 
data[1].weight=1; data[1].x=2; data[1].y=-48.0; 
data[2].weight=1; data[2].x=3; data[2].y=-43.0; 
data[3].weight=1; data[3].x=4; data[3].y=-44.0; 
data[4].weight=1; data[4].x=5; data[4].y=-35.0; 
data[5].weight=1; data[5].x=6; data[5].y=-31.0; 
data[6].weight=1; data[6].x=7; data[6].y=-32.0; 
data[7].weight=1; data[7].x=8; data[7].y=-43.0; 
data[8].weight=1; data[8].x=9; data[8].y=-52.0; 

double a=0.0, b=0.0, c=0.0;
findQuadraticFactors(data, a, b, c, 9);
std::cout << " x \t y" << std::endl;
for (int i=0; i<9; ++i)
    {
    std::cout << " " << data[i].x << ", " << findY(a,b,c,data[i].x) << std::endl;
    }
}

答案 2 :(得分:0)

也许您的运行平均值的参数设置错误(样本窗口太小或太大)?

只是噪音叠加在钟形曲线上吗?噪声频率与您尝试检索的信号的接近程度有多近?您尝试提取的内容可能有助于我们确定解决方案。

如果您可以合理地猜测函数参数,可以使用least squares fit尝试某种拟合算法。这些技术通常对噪音有一定的免疫力。

答案 3 :(得分:0)

简单的数字low-pass filter怎么样?

y[0] = x[0];
for (i = 1; i < len; ++i)
    y[i] = a * x[i] + (1.0 - a) * y[i - 1];

在这种情况下, x [] 是输入数据, y [] 是过滤后的输出。 a 系数是一个介于0和1之间的值,您应该进行调整。当 a 接近0时, a 值为1会再现输入,cut-off frequency会减少。