使用Python进行曲线拟合时遭遇exp溢出及无效标量值错误的问题求助
Let's break down these two warnings and fix them step by step:
Why You're Seeing These Warnings
1. RuntimeWarning: overflow encountered in exp
This happens when curve_fit tests parameter combinations that make the input to np.exp() way too large (positive) for floating-point numbers to handle, resulting in an infinite value (inf). Looking at your fit function:
R1_fit_Curve = ( a0 * np.exp( a1 * (1 - (28 / t)**(4 / 5)) ) + a2 * (t / ((a3)**a4 + t**a4)) )
When t is very small (like 0.052 in your first dataset, or ≈0.0173 in the second), 28/t becomes a huge number, so (28/t)**(4/5) is also massive. If the fitting process tries a negative value for a1, then a1 * (1 - huge_number) becomes a large positive number (since 1 - huge_number is negative, negative × negative = positive). np.exp(large_positive) will overflow to inf, triggering this warning.
Even with a positive a1, extreme parameter values during iteration could still cause overflow, but the negative a1 scenario is the most likely culprit here.
2. RuntimeWarning: invalid value encountered in double_scalars
This one's almost certainly caused by NaN values from raising a negative number to a non-integer power. Your function includes a3**a4, and your initial a4 value is ≈1.51 (a non-integer). When curve_fit iterates parameters, if a3 becomes negative, raising a negative number to a non-integer power isn't defined in the real number system—numpy returns NaN for this operation, which then propagates through your calculations and triggers the warning.
Adding smaller t values in your second dataset makes the parameter iteration more likely to hit these edge cases, which is why this warning pops up only after expanding your data.
Fixes to Try
1. Add Reasonable Parameter Bounds
The bounds argument in curve_fit lets you restrict parameters to valid ranges, eliminating the invalid combinations that cause warnings:
- For
a3: Sincea3**a4requiresa3 ≥ 0whena4is non-integer, set a lower bound of a tiny positive number (like1e-8) to avoid negative values or division by zero. - For
a1: Based on your Matlab success,a1should be positive—set its lower bound to1e-8to prevent negative values that causeexpoverflow. - For other parameters (
a0,a2,a4), use positive lower bounds too, since they likely represent physical quantities that can't be negative.
Here's the updated curve_fit call:
pars, cov = curve_fit( f=func_R1_fit, xdata=tau_array, ydata=array_R1_fit, p0=[0.249714296337621, 0.101851223776512, 0.209343265573669, 0.306273529630680, 1.511897539010256], # Define bounds as (lower_bounds, upper_bounds) tuples bounds=( (1e-8, 1e-8, 1e-8, 1e-8, 1e-8), # All parameters start from a tiny positive value (np.inf, np.inf, np.inf, np.inf, np.inf) # No upper limit unless you have domain knowledge ), maxfev=100000 )
If you know a4 should be in a specific range (like 1–2 based on your initial value), tighten its bounds further to make fitting more stable.
2. Simplify Large Value Calculations (Optional)
The huge 28/t term can cause numerical instability. Rewrite your function to avoid calculating large powers directly by scaling the term:
# Redefined function to use 1/t instead of 28/t (mathematically equivalent) def func_R1_fit_scaled(t, a0, a1_scaled, a2, a3, a4): # We absorb 28^(4/5) into a1_scaled to keep numbers smaller term1 = a0 * np.exp( a1_scaled * (1 - (1/t)**(4/5)) ) term2 = a2 * (t / ((a3)**a4 + t**a4)) return term1 + term2 # Adjust the initial a1 value to account for the scaling factor scaling_factor = 28 ** (4/5) a1_scaled_p0 = 0.101851223776512 * scaling_factor pars_scaled, cov_scaled = curve_fit( f=func_R1_fit_scaled, xdata=tau_array, ydata=array_R1_fit, p0=[0.249714296337621, a1_scaled_p0, 0.209343265573669, 0.306273529630680, 1.511897539010256], bounds=( (1e-8,1e-8,1e-8,1e-8,1e-8), (np.inf,np.inf,np.inf,np.inf,np.inf) ), maxfev=100000 )
This reduces the size of the numbers you're raising to a power, making the calculation more stable.
3. Check for Outliers in Your Data
In your second dataset, the point t≈0.0173 (0.052/3) has a y-value of 3.095, which is much lower than the adjacent point t=0.04 (y=13.83). If this is an experimental error, removing it might not only fix the warning but also improve your fit quality.
How to Verify
After adding parameter bounds, run your code again—both warnings should disappear. If you still see issues, you can debug by tracking parameter values during fitting (use scipy.optimize.least_squares instead of curve_fit for built-in callback support) to see which parameters are hitting invalid ranges.
内容的提问来源于stack exchange,提问作者Ali AlCapone

