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

使用Scipy拟合Rice分布出现异常结果的问题排查

Rice分布拟合失败的问题分析与修正

你的代码存在几个关键错误,导致拟合结果无意义,以下是问题点和修正方案:

1. 自定义Rice PDF公式核心缺失

你实现的rice_pdf遗漏了零阶第一类修正贝塞尔函数I₀,这是Rice分布PDF的核心组成部分。正确的Rice分布PDF公式为:

$f(x; b, \nu) = \frac{x}{b^2} \exp\left(-\frac{x^2 + \nu2}{2b2}\right) I_0\left(\frac{x\nu}{b^2}\right)$

同时你添加的amplitude参数是冗余的——直方图已经设置density=True,PDF本身是归一化的,不需要额外振幅缩放。

2. 拟合后分布对象的参数逻辑错误

你创建拟合分布时使用rice(nu, loc=scale, scale=np.sqrt(b**2 + scale**2))完全不符合scipy.stats.rice的参数定义,该分布的构造格式为rice(b, loc=loc, scale=scale),其中b是形状参数(对应$\nu/\sigma$),loc是位置偏移,scale是缩放参数$\sigma$。

3. 初始猜测参数不合理

初始猜测的参数数量冗余且取值不符合Rice分布的参数逻辑,容易导致拟合算法收敛到局部最优或无意义解。


修正后的完整代码

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import rice
from scipy.optimize import curve_fit
from scipy.special import iv  # 导入零阶修正贝塞尔函数

# 符合scipy定义的Rice PDF函数
def rice_pdf(x, b, scale, loc=0):
    x_shifted = x - loc
    # 处理Rice分布定义域(x >= loc)
    x_shifted[x_shifted < 0] = 0
    nu = b * scale
    return (x_shifted / scale**2) * np.exp(-(x_shifted**2 + nu**2) / (2 * scale**2)) * iv(0, (x_shifted * nu) / scale**2)

def fit_rice_distribution_to_histogram(hist_data, bins):
    bin_centers = (bins[:-1] + bins[1:]) / 2

    # 基于数据特征的合理初始猜测
    data_std = np.std(bin_centers)
    initial_guess = [0.8, data_std, 0]
    # 限制参数范围避免无意义解
    bounds = ([0, 0, -np.inf], [np.inf, np.inf, min(bin_centers)])
    
    params, covariance = curve_fit(rice_pdf, bin_centers, hist_data, p0=initial_guess, bounds=bounds)
    b_fit, scale_fit, loc_fit = params

    # 创建正确的拟合分布对象
    fitted_distribution = rice(b=b_fit, loc=loc_fit, scale=scale_fit)
    return fitted_distribution, b_fit, scale_fit, loc_fit

if __name__ == "__main__":
    # 真实分布参数
    nu_true = 8.5
    sigma_true = 10.5
    sample_size = 1000  # 增大样本量让直方图更接近真实PDF
    b_true = nu_true / sigma_true

    # 生成Rice分布数据
    data = rice.rvs(b=b_true, scale=sigma_true, size=sample_size)

    # 绘制归一化直方图
    hist_data, bins, _ = plt.hist(data, bins=30, density=True, alpha=0.5, label="生成数据")
    plt.xlabel("数值")
    plt.ylabel("概率密度")

    # 拟合分布
    fitted_dist, b_fit, scale_fit, loc_fit = fit_rice_distribution_to_histogram(hist_data, bins)

    # 绘制拟合曲线
    x = np.linspace(min(bins), max(bins), 1000)
    pdf_values = fitted_dist.pdf(x)
    plt.plot(x, pdf_values, 'r-', label="拟合Rice分布")
    plt.legend()
    plt.show()

    # 输出参数对比
    print(f"真实参数:b={b_true:.4f}, sigma={sigma_true}, nu={nu_true}")
    print(f"拟合参数:b={b_fit:.4f}, scale={scale_fit:.4f}, loc={loc_fit:.4f}")
    print(f"推导的nu(b*scale):{b_fit*scale_fit:.4f}")

额外优化说明

  • 增大样本量到1000,让直方图更接近真实PDF,提升拟合稳定性;
  • 添加参数边界限制,避免拟合出负数等无意义参数;
  • 移除冗余的amplitude参数,保持PDF与归一化直方图的一致性;
  • 修正了分布对象的参数传递逻辑,确保拟合曲线与真实分布匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 13:25:38