3

我正在做一些特定的信号分析,我需要一种方法来平滑给定的钟形分布曲线。运行平均方法不会产生我想要的结果。我想保持拟合曲线的最小/最大值和一般形状完整,但要解决采样中的不一致问题。

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

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

谢谢!

编辑:一些有用的数据

(可能的信号图)

替代文字

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

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

4

4 回答 4

3

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

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

另一方面,如果您想用二次近似平滑曲线,我建议计算具有最小平方误差的二次多项式。我不记得这个公式,但如果你有微积分,写出总平方误差的公式(逐点)并根据你的二次系数进行微分。将一阶导数设置为零并求解最佳近似值。或者你可以查一下。

最后,如果您只想要一条看起来平滑的曲线来逼近一组点,三次样条曲线是您最好的选择。曲线不一定意味着任何东西,但你会得到一个很好的平滑近似值。

于 2010-04-06T02:22:49.127 回答
3
#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;
    }
}
于 2011-08-09T18:52:03.683 回答
0

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

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

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

于 2010-04-06T01:28:34.997 回答
0

一个简单的数字低通滤波器怎么样?

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值 1 再现输入,并且截止频率随着a接近 0 而降低。

于 2010-04-06T01:30:29.180 回答