Scipy/Fitter拟合数据分布遇问题:缩放异常及适配方案咨询
问题1:为何示例中的分布缩放程度低于真实数据?
核心原因是拟合对象的本质差异:
- 你的原始数据是实际观测的绝对值,比如
y中的8.8、7.2都是直接测量/统计得到的具体数值。 - 而
fitter或scipy的分布拟合工具,默认针对数据的**概率密度函数(PDF)**进行拟合。PDF要求在整个取值范围内的积分等于1,工具会自动将数据归一化到这个尺度,导致拟合曲线的高度远低于原始数据的绝对值——它描述的是“某个取值出现的概率密度”,而非数据本身的数值大小。
问题2:针对你的数据,如何拟合出合理的结果?
首先明确:你的x是有序自变量(1到19的序列),y是随x变化的因变量,呈现先快速衰减、后小幅波动的趋势,更适合做曲线回归拟合(即寻找y与x的函数关系),而非传统的独立样本分布拟合(后者适用于无关联的随机样本)。
可行代码示例
步骤1:数据可视化,观察趋势
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit # 你的数据 y = np.array([8.8,7.2,5.8,4.7,3.8,3.1,2.6,2.2,2.0,1.7,1.8,1.8,1.9,1.7,1.4,1.2,1.7,1.2,1.5]) x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) plt.scatter(x, y, label='原始数据') plt.xlabel('x') plt.ylabel('y') plt.legend() plt.show()
步骤2:选择拟合模型并执行拟合
观察数据趋势,采用指数衰减+常数项的模型(匹配先衰减后稳定的特征):
$$y = a \cdot e^{-b \cdot x} + c$$
其中a是初始衰减幅度,b是衰减速率,c是稳定后的基线值。
# 定义拟合函数 def decay_model(x, a, b, c): return a * np.exp(-b * x) + c # 初始参数猜测(根据数据趋势估算) initial_guess = [8, 0.1, 1.5] # 执行拟合 params, covariance = curve_fit(decay_model, x, y, p0=initial_guess) a_fit, b_fit, c_fit = params print(f"拟合参数:a={a_fit:.2f}, b={b_fit:.2f}, c={c_fit:.2f}") # 生成拟合曲线并可视化 y_fit = decay_model(x, a_fit, b_fit, c_fit) plt.scatter(x, y, label='原始数据') plt.plot(x, y_fit, color='red', label=f'拟合曲线: y={a_fit:.2f}e^(-{b_fit:.2f}x)+{c_fit:.2f}') plt.xlabel('x') plt.ylabel('y') plt.legend() plt.show()
补充:若需拟合y的概率分布(忽略x的关联)
如果坚持把y当成独立样本拟合分布,可尝试对数正态分布(匹配y的右偏分布特征):
from scipy.stats import lognorm # 拟合对数正态分布 shape, loc, scale = lognorm.fit(y, floc=0) print(f"对数正态分布参数:shape={shape:.2f}, loc={loc:.2f}, scale={scale:.2f}") # 可视化拟合结果 y_values = np.linspace(min(y), max(y), 100) pdf = lognorm.pdf(y_values, shape, loc, scale) plt.hist(y, bins=5, density=True, alpha=0.5, label='y的概率密度') plt.plot(y_values, pdf, color='red', label='拟合的对数正态PDF') plt.xlabel('y') plt.ylabel('概率密度') plt.legend() plt.show()
注意:这种拟合会忽略x与y的关联,仅能描述y的整体取值分布,无法体现随x的变化趋势。
内容的提问来源于stack exchange,提问作者Sam Huguet
相关产品推荐
相关产品推荐

