用scipy拟合一个rice分布

zzoitvuj  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(147)

我试图写一个fitter一些大米分布式数据,我有,但它是不工作的一些,可能是愚蠢的,原因。
分布创建得很好,拟合路由似乎与我习惯的高斯分布一样。然而,当我拟合曲线时,我只是胡说八道。似乎看不出我哪里出错了。

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import rice
from scipy.optimize import curve_fit

# Custom Rice PDF function
def rice_pdf(x, nu, amplitude, b, scale):
    return (x / b) * np.exp(-(x**2 + scale**2) / (2 * b**2)) * amplitude

# Function to fit a Rice distribution to a histogram using curve_fit
def fit_rice_distribution_to_histogram(hist_data, bins):
    # Calculate bin centers
    bin_centers = (bins[:-1] + bins[1:]) / 2

    # Initial guesses for the parameters (nu, amplitude, b, scale)
    initial_guess = [8.4, 1.0, 1.0, np.mean(bin_centers)]

    # Fit the Rice distribution to the histogram data using curve_fit
    params, covariance = curve_fit(rice_pdf, bin_centers, hist_data, p0=initial_guess)
    nu, amplitude, b, scale = params

    # Create the fitted Rice distribution
    fitted_distribution = rice(nu, loc=scale, scale=np.sqrt(b**2 + scale**2))

    return fitted_distribution, nu, amplitude, b, scale

# Example usage:
if __name__ == "__main__":
    # Parameters for the Rice distribution
    nu = 8.5
    sigma = 10.5
    sample_size = 100

    # Calculate b from nu and sigma
    b = nu / sigma

    # Generate random data points from the Rice distribution
    data = rice.rvs(b=b, scale=sigma, size=sample_size)

    # Create a histogram of the generated data
    hist_data, bins, _ = plt.hist(data, bins=20, density=True, alpha=0.5, label="Generated Data")
    plt.xlabel("Value")
    plt.ylabel("Probability Density")

    # Fit a Rice distribution to the histogram using curve_fit
    fitted_distribution, fitted_nu, amplitude, fitted_b, fitted_scale = fit_rice_distribution_to_histogram(hist_data, bins)

    # Plot the original histogram and the fitted distribution
    x = np.linspace(min(bins), max(bins), 1000)
    pdf_values = fitted_distribution.pdf(x)
    plt.plot(x, pdf_values, 'r', label="Fitted Rice Distribution")
    plt.legend()
    plt.show()

    # Print fitted parameters
    print("Fitted Nu:", fitted_nu)
    print("Fitted Amplitude:", amplitude)
    print("Fitted b:", fitted_b)
    print("Fitted Scale:", fitted_scale)

字符串

dy1byipe

dy1byipe1#

根据您提供的试验数据集:

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats, optimize

nu = 8.5
sigma = 10.5
n = 100
b = nu / sigma

np.random.seed(12345)

# Reference Distribution:
X = stats.rice(b=b, scale=sigma)

# Binned dataset:
data = X.rvs(size=n)
density, bins = np.histogram(data, density=1.)
centers = (bins[:-1] + bins[1:]) / 2

字符串
从那里我们可以从直方图数据中估计参数:

def model(x, b, loc, scale):
    return stats.rice.pdf(x, b=b, loc=loc, scale=scale)

popt, pcov = optimize.curve_fit(model, centers, density)


模型函数与您的模型函数有很大不同,因为它缺少文档中指定的贝塞尔函数项。

xlin = np.linspace(0, 50, 200)
fig, axe = plt.subplots()
axe.hist(data, alpha=0.5, density=1.0, label="Data")
axe.plot(xlin, X.pdf(xlin), label="Model")
axe.plot(xlin, model(xlin, *popt), label="Fit")
axe.legend()
axe.grid()


的数据
n=10000和箱数增加到100会得到准确的结果:


的数据

更新

你有两个方法来取回你的参数。在scipy中默认应用的变量变化之间进行数学运算。或者按照定义重写函数。

def rice(x, nu, sigma):
    return (x/sigma**2)*np.exp(-0.5*(x**2 + nu**2)/sigma**2)*special.i0(x*nu/sigma**2)


然后,您可以直接拟合参数:

popt2, pcov2 = optimize.curve_fit(rice, centers, density, p0=[10, 10])

#  array([ 8.86411171, 10.34217091]),
#  array([[ 0.12896075, -0.06411305],
#         [-0.06411305,  0.03441797]])


相关问题