c++ 一维高斯拟合_基于C语言的高斯曲线拟合原理以及实现【转】

https://blog.csdn.net/dingzj2000/article/details/103719368?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control

1.意义

高斯曲线 ,又叫做gaussian curve,是正态分布中的一条标准曲线。具有以下特征:

1.1 正态曲线在横轴上方均数处最高;

1.2 正在分布以均数为中心,左右对称;

1.3 正态分布有两个参数,即均数和标准差;标准正态分布用N(0,1)表示;

1.4 正态曲线下的面积分布有一定的规律。

在分析仪器的测量中,有许多具有明确的物理意义的二维图谱,如光谱图、色谱图等,许多测量图谱都可以用高斯曲线予以描述。高斯曲线虽然也是非线性函数,但它的各个参数具有明确的物理意义,因为高斯拟合在分析仪器的测量中具有广泛的应用前景。利用它来描述或拟合求出一些实验数据的分析,往往能起到常规方法不能达到的作用。

2.结果展示

最近在做一个医用仪器项目,需要用到高斯拟合,之前也没有搞过相关内容,于是先在PC端实现高斯拟合函数,能够实现要求后,再移植到仪器上使用。

先展示一下结果:

图2.1 高斯曲线拟合

先随机选6个测试点(蓝色点),根据这6个测试点,进行高斯拟合,红色曲线就是拟合出来的曲线。拟合出来的曲线基本在选取的6个测试点附近。通过这6个点,找出了互相之间的关系。达到了设计目的。

3.原理

高斯拟合即使用形如:Gi(x) = Ai*exp((x-Bi)^2/Ci^2)的高斯函数对数据点集进行函数逼近的拟合方法,高斯拟合跟多项式拟合类似,不同的是多项式拟合是用幂函数系,而高斯拟合用的是高斯函数系。使用高斯函数拟合来进行拟合,优点在于计算积分十分简单快捷。

3.1 高斯函数

高斯函数:

a表示得到曲线的高度,c是指曲线在x轴的中心,b指width(与半峰全宽有关),图形如下:图形如下:

3.2 高斯拟合原理

设有一组实验数据

(i = 1,2,3,...N),可用高斯函数描述:

式(3.1)中待估参数a,c和b,分别代表的物理意义为高斯曲线的峰高、峰位置和半宽度信息。将式(3.1)两边取自然对数,化为:

则式(3.2)化为二次多项式拟合函数

考虑全部数据和测量误差,并以矩阵形式表示如下

简记为:

在不考虑总量程误差E的影响情况下,根据最小二乘原理,可求得拟合常数b0,b1,b2构成的矩阵B的广义最小二乘解为:

进而根据式(3.3),可求得待估参数a,b,c:

     ,  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你不想使用额外的数学库,也可以在 C++实现二维高斯曲线拟合。以下是一个简单的示例代码: ```c++ #include <iostream> #include <cmath> using namespace std; const int N = 100; double x[N], y[N], z[N]; int main() { // 读入数据,假设数据已经被归一化到 [0, 1] 的范围内 for (int i = 0; i < N; i++) { cin >> x[i] >> y[i] >> z[i]; } // 初始化参数 double a = 1, b = 0.5, c = 0.5, d = 0.5, e = 0.5, f = 0; // 迭代求解参数 const double eps = 1e-6; double last_loss = 1e9; for (int iter = 0; iter < 100; iter++) { double loss = 0; double sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0; for (int i = 0; i < N; i++) { double xi = x[i], yi = y[i], zi = z[i]; double ti = a*exp(-((xi-b)*(xi-b)/c + (yi-d)*(yi-d)/e)) + f; double err = ti - zi; loss += err * err; sa += err * exp(-((xi-b)*(xi-b)/c + (yi-d)*(yi-d)/e)); sb += err * a * exp(-((xi-b)*(xi-b)/c + (yi-d)*(yi-d)/e)) * (xi-b) / c; sc += err * a * exp(-((xi-b)*(xi-b)/c + (yi-d)*(yi-d)/e)) * (xi-b)*(xi-b)/(c*c); sd += err * a * exp(-((xi-b)*(xi-b)/c + (yi-d)*(yi-d)/e)) * (yi-d) / e; se += err * a * exp(-((xi-b)*(xi-b)/c + (yi-d)*(yi-d)/e)) * (yi-d)*(yi-d)/(e*e); sf += err; } if (loss > last_loss) break; // 如果损失函数不再下降,则停止迭代 last_loss = loss; a -= sa * eps; b -= sb * eps; c -= sc * eps; d -= sd * eps; e -= se * eps; f -= sf * eps; } // 输出结果 cout << "a = " << a << ", b = " << b << ", c = " << c << ", d = " << d << ", e = " << e << ", f = " << f << endl; return 0; } ``` 这里使用了梯度下降算法求解参数,具体实现可以参考代码注释。需要注意的是,这里假设数据已经被归一化到 [0, 1] 的范围内,因此在实际应用中需要根据数据的实际情况进行归一化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值