You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用scipy.stats.beta建模不对称色谱峰曲线?

色谱峰Beta分布拟合问题排查

我正在开展色谱峰积分工作,需通过峰形建模精准判定峰的起止位置。目前能成功拟合高斯峰,但多数色谱峰存在不对称性,这类峰更适合采用Beta分布建模。现在我能拟合高斯模型,却无法得到匹配峰形的Beta模型,想咨询问题出在哪里?我查阅了多篇Stack Overflow相关帖子,但均未演示如何将推导的模型叠加在原始数据上以展示拟合效果。

原代码(存在错误)

from scipy.stats import beta
import plotly.graph_objects as go
import peakutils

# raw data 
yy = [128459, 1822448, 10216680, 24042041, 30715114, 29537797, 25022446, 18416199, 14138783, 12116635, 9596337, 7201602, 5668133, 4671416, 3920953, 3259980, 2756295, 2326780, 2095209, 1858894, 1646824, 1375129, 1300799, 1253879, 1086045, 968363, 932041, 793707, 741462, 741593]
xx = list(range(0,len(yy)))
fig = go.Figure()
fig.add_trace(go.Scatter(x = xx, y = yy, name = 'raw', mode = 'lines'))

# Gaussian model
gamp, gcen, gwid = peakutils.peak.gaussian_fit(xx, yy, center_only= False) # this calculates the Amplitude, Center & Width of a guassian peak
print(gamp, gcen, gwid)
gauss_model = [peakutils.peak.gaussian(x, gamp, gcen, gwid) for x in xx]
fig.add_trace(go.Scatter(x = xx, y = gauss_model, mode = 'lines', name = 'Gaussian'))

# Beta distribution model
aa, bb, loc, scale = beta.fit(dat)  # 错误:dat未定义,应传入yy
print('beta fit:', beta_fit)  # 错误:beta_fit未定义,应输出拟合参数
beta_model = beta.pdf(xx, aa, bb, loc, scale)
fig.add_trace(go.Scatter(x = xx, y = beta_model, mode = 'lines', name = 'Beta'))

fig.show()

拟合效果说明

原始拟合图中,高斯曲线与峰形贴合较好,但Beta分布曲线数值极小,完全无法匹配原始峰形的振幅和趋势。

问题根源与修正方案

核心问题点

  • 数据定义域不匹配:Beta分布默认仅在[0,1]区间有非零概率密度,而你的x轴范围是0-29,直接拟合会导致参数失效
  • 变量定义错误:代码中dat和beta_fit未定义,属于语法错误
  • 拟合目标偏差:beta.fit是对数据做概率密度分布拟合,而你需要的是峰形曲线拟合(需匹配原始数据的振幅),两者目标完全不同
  • 振幅未适配:Beta概率密度的输出范围远小于原始数据的百万级峰值,直接使用会导致曲线几乎不可见

修正后的代码

from scipy.stats import beta
import plotly.graph_objects as go
import peakutils
import numpy as np
from scipy.optimize import curve_fit

# 原始数据
yy = [128459, 1822448, 10216680, 24042041, 30715114, 29537797, 25022446, 18416199, 14138783, 12116635, 9596337, 7201602, 5668133, 4671416, 3920953, 3259980, 2756295, 2326780, 2095209, 1858894, 1646824, 1375129, 1300799, 1253879, 1086045, 968363, 932041, 793707, 741462, 741593]
xx = np.arange(len(yy))
fig = go.Figure()
fig.add_trace(go.Scatter(x=xx, y=yy, name='原始数据', mode='lines'))

# 高斯模型拟合(保留原有逻辑)
gamp, gcen, gwid = peakutils.peak.gaussian_fit(xx, yy, center_only=False)
gauss_model = [peakutils.peak.gaussian(x, gamp, gcen, gwid) for x in xx]
fig.add_trace(go.Scatter(x=xx, y=gauss_model, mode='lines', name='高斯拟合'))

# 自定义Beta峰形模型:包含振幅、形状参数、位置和缩放参数
def beta_peak(x, amp, a, b, loc, scale):
    # 将x归一化到Beta分布的[0,1]定义域
    x_norm = (x - loc) / scale
    # 用振幅缩放概率密度值,匹配原始峰高
    return amp * beta.pdf(x_norm, a, b)

# 初始化拟合参数:振幅用原始峰值,loc/scale覆盖x范围,a/b初始设为2(接近对称)
x_min, x_max = xx.min(), xx.max()
init_params = [yy.max(), 2, 2, x_min, x_max - x_min]

# 用curve_fit拟合自定义模型,以峰形匹配为目标
popt, _ = curve_fit(beta_peak, xx, yy, p0=init_params)
amp_fit, a_fit, b_fit, loc_fit, scale_fit = popt

# 生成拟合后的Beta峰形曲线
beta_model = beta_peak(xx, *popt)
fig.add_trace(go.Scatter(x=xx, y=beta_model, mode='lines', name='Beta拟合'))

print("Beta拟合参数(振幅, 形状a, 形状b, 位置, 缩放):", popt)
fig.show()

修正要点说明

  1. 自定义了带振幅参数的Beta峰形模型,解决概率密度值与原始峰振幅不匹配的问题
  2. 对x轴做归一化转换,适配Beta分布的[0,1]定义域要求
  3. 使用curve_fit替代默认的beta.fit,将拟合目标从概率密度分布改为峰形曲线匹配
  4. 修正了原代码中的变量未定义错误

内容的提问来源于stack exchange,提问作者Ninja Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 18:34:51