繁体   English   中英

用指数负对数似然最小化拟合指数衰减不收敛

[英]Fitting exponential decay with scipy negative log likelihood minimization not converging

在此处输入图片说明 我正在尝试使用对数似然最小化来拟合指数衰减函数,但是即使对于最小化器而言,具有良好的起始参数x0 ,我似乎也无法使其收敛。 为什么? 我写错了吗?

编辑以包括传统的归类似然又称为“曲线”拟合

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

np.random.seed(1)

def exp_fit(x, N, L):
    return N * np.exp(- L * x)

def negloglik(args, func, data):
    """Negative log likelihood"""
    return - np.sum(np.log(func(data, *args)))

def histpoints_w_err(X, bins):
    counts, bin_edges = np.histogram(X, bins = bins, normed = False)
    bin_centers       = (bin_edges[1:] + bin_edges[:-1]) / 2
    bin_err           = np.sqrt(counts)

    # Generate fitting points
    x  = bin_centers[counts > 0]  # filter along counts, to remove any value in the same position as an empty bin
    y  = counts[counts > 0]
    sy = bin_err[counts > 0]

    return x, y, sy

data = np.random.exponential(0.5, 1000)
bins = np.arange(0, 3, 0.1)

x, y, sy = histpoints_w_err(data, bins)
popt, pcov = curve_fit(exp_fit, x, y, sigma = sy)

xpts = np.linspace(0, 3, 100)


# All variables must be positive
bnds = ((0, None),
        (0, None))

result = minimize(negloglik,
                  args = (exp_fit, data),
                  x0 = (popt[0], popt[1]), # Give it the parameters of the fit that worked
                  method = "SLSQP",
                  bounds = bnds)

jac = result.get("jac")

plt.hist(data, bins = bins)
plt.plot(xpts, exp_fit(xpts, *popt), label = "Binned fit: {:.2f}exp(-{:.2f}x)".format(*popt))
plt.plot(xpts, exp_fit(xpts, *jac), label = "Unbinned fit: {:.2f}exp(-{:.2f}x)".format(*jac))
plt.text(s = result, x = 0.8, y = popt[0]*0.2)
plt.legend()
plt.show()

我删除了这样的方法:

# minimize the negative log-Likelihood
result = minimize(negloglik,  args = (exp_fit, data), x0 = (15, 0.5))

我得到的是:

      fun: -1601.1177190942697
 hess_inv: array([[2.16565679e+11, 5.15680574e+09],
       [5.15680574e+09, 1.22792520e+08]])
      jac: array([0., 0.])
  message: 'Optimization terminated successfully.'
     nfev: 120
      nit: 28
     njev: 30
   status: 0
  success: True
        x: array([8986009.32851534,  213973.66153225])

以前的成功是错误的。 也许应该将方法更改为其他方法? 如果未指定,默认值是BFGS,L-BFGS-B,SLSQP,具体取决于问题是否具有约束或界限。

因此,使用iminuit和probfit而不是scipy重做整个事情。 语法有点怪异(特别是iminuit如何更改输入参数名称以匹配拟合参数),但是一旦开始,它的使用就非常简单。 可惜的是,关于此的社区文档很少。

在这里,我完成了无限似然拟合:

import iminuit, probfit
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats

np.random.seed(1)
data = np.random.exponential(0.5, 500)

def unbinned_exp_LLH(data, loc_init, scale_init, limit_loc, limit_scale):
    # Define function to fit
    def exp_func(x, loc, scale):
        return scipy.stats.expon.pdf(x, loc, scale)

    # Define initial parameters
    init_params = dict(loc = loc_init, scale = scale_init)

    # Create an unbinned likelihood object with function and data.
    unbin = probfit.UnbinnedLH(exp_func, data)

    # Minimizes the unbinned likelihood for the given function
    m = iminuit.Minuit(unbin,
                       **init_params,
                       limit_scale = limit_loc,
                       limit_loc = limit_scale,
                       pedantic=False,
                       print_level=0)
    m.migrad()
    params = m.values.values() # Get out fit values
    errs   = m.errors.values()
    return params, errs


params, errs = unbinned_exp_LLH(data, loc_init = 0, scale_init = 0.5, limit_loc = (-1, 1), limit_scale = (-1, 1))

loc, scale = params

# Plot
x_pts = np.linspace(0, 3, 100)
plt.plot(x_pts, scipy.stats.expon.pdf(x_pts, *params), label = "exp(-{1:.2f}x)".format(*params), color = "black")
plt.hist(data, color = "lightgrey", bins = 20, label = "generated data", normed = True)
plt.xlim(0, 3)
plt.legend()
plt.show()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM