Skip to content

Difference between 2D and 1D Confidence Regions #848

@ThiagoReschutzegger

Description

@ThiagoReschutzegger

Yes, I read the instructions and I am sure this is a GitHub Issue.

Python: 3.10.9 (main, Jan 11 2023, 09:18:20) [Clang 14.0.6 ]

lmfit: 1.1.0, scipy: 1.10.0, numpy: 1.23.5,asteval: 0.9.28, uncertainties: 3.1.7

Apparently, there is a difference in calculating the confidence region using the conf_interval or the conf_interval2d method. It was expected that when plotting the regions calculated by both methods (as I did below), the 1D confidence region would be overlapping the maximum points and minima of the 2D region. However, the results show a significant deviation from this expectation.

I would like to investigate this issue further, but before doing so, I need to know whether this behavior is expected or not. If it is not expected, I can focus on understanding the underlying reasons behind this behavior.

Can anyone provide any insights or guidance regarding this issue? Any help would be greatly appreciated.

# same code from Documentation Example
import matplotlib.pyplot as plt
import numpy as np
import lmfit

x = np.linspace(1, 10, 250)
np.random.seed(0)
y = 3.0*np.exp(-x/2) - 5.0*np.exp(-(x-0.1)/10.) + 0.1*np.random.randn(x.size)

p = lmfit.Parameters()
p.add_many(('a1', 4.), ('a2', 4.), ('t1', 3.), ('t2', 3.))

def residual(p):
    return p['a1']*np.exp(-x/p['t1']) + p['a2']*np.exp(-(x-0.1)/p['t2']) - y

mini = lmfit.Minimizer(residual, p, nan_policy='propagate')

out1 = mini.minimize(method='Nelder')
out2 = mini.minimize(method='leastsq', params=out1.params)

# arrays to store bounds for three different sigma values (1, 2, and 3)
bound_a1 = np.zeros((3, 2))
bound_a2 = np.zeros((3, 2))
bound_t1 = np.zeros((3, 2))
bound_t2 = np.zeros((3, 2))

# calculate and store respective confidence intervals
for i, sig in enumerate([1, 2, 3]):
    ci, trace = lmfit.conf_interval(mini, out2, sigmas=[sig], trace=True)
    bound_a1[i] = (ci['a1'][0][1], ci['a1'][-1][1])
    bound_a2[i] = (ci['a2'][0][1], ci['a2'][-1][1])
    bound_t1[i] = (ci['t1'][0][1], ci['t1'][-1][1])
    bound_t2[i] = (ci['t2'][0][1], ci['t2'][-1][1])

colors = ['r', 'b', 'g']
levels = [0.683, 0.955, 0.997]

# plot confidence intervals (a1 vs t2 and a2 vs t2)
fig, axes = plt.subplots(1, 2, figsize=(12.8, 4.8))
cx, cy, grid = lmfit.conf_interval2d(mini, out2, 'a1', 't2', 200, 200)
ctp = axes[0].contourf(cx, cy, grid, np.linspace(0, 1, 501), cmap='gray')
axes[0].contour(cx, cy, grid, levels=levels, colors=colors)
fig.colorbar(ctp, ax=axes[0])
axes[0].set_xlabel('a1')
axes[0].set_ylabel('t2')

# plot boxes
for i, c in zip(range(3), colors):
    axes[0].plot([bound_a1[i][0], bound_a1[i][1], bound_a1[i][1], bound_a1[i][0], bound_a1[i][0]],
                 [bound_t2[i][0], bound_t2[i][0], bound_t2[i][1], bound_t2[i][1], bound_t2[i][0]],
                 color=c, linestyle='--', alpha=0.5)

cx, cy, grid = lmfit.conf_interval2d(mini, out2, 'a2', 't2', 200, 200)
ctp = axes[1].contourf(cx, cy, grid, np.linspace(0, 1, 501), cmap='gray')
axes[1].contour(cx, cy, grid, levels=levels, colors=colors)
fig.colorbar(ctp, ax=axes[1])
axes[1].set_xlabel('a2')
axes[1].set_ylabel('t2')

# plot boxes
for i, c in zip(range(3), colors):
    axes[1].plot([bound_a2[i][0], bound_a2[i][1], bound_a2[i][1], bound_a2[i][0], bound_a2[i][0]],
                 [bound_t2[i][0], bound_t2[i][0], bound_t2[i][1], bound_t2[i][1], bound_t2[i][0]],
                 color=c, linestyle='--', alpha=0.5)

plt.show()

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions