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

Scipy拟合真实指数衰减数据时exp溢出警告的解决及模型适配问题

Hey there! Let's work through your problem together.

First: Is your model function a good fit for the data?

Absolutely! The dataset you shared clearly shows an exponential decay trend—starting high and tapering off to a steady baseline value. Your A*exp(-K*x)+C model is perfect for this pattern:

  • A represents the initial amplitude (the difference between the starting value and the baseline)
  • K is the decay constant (controls how fast the value drops)
  • C is the asymptotic baseline (the value y approaches as x gets very large)

Why are you seeing the overflow error and bad fit?

The issue comes down to numerical instability and poor initial parameter guesses:

  1. The default initial guess for curve_fit is [1,1,1], which is totally mismatched for your data. When the algorithm starts iterating, it might try negative values for K, which turns exp(-K*x) into exp(large_positive_number)—that's what causes the overflow warning.
  2. Even with positive K, your x-values go up to ~5000 (and eventually 1e6), so exp(-K*x) can become extremely small or large if K isn't scaled properly, throwing off the fitting process.

Fixes to get a good fit

Here's how to adjust your code to get accurate parameters:

1. Estimate reasonable initial parameters

Instead of letting curve_fit guess blindly, calculate initial values based on your data:

  • C: Take the minimum value of y (your baseline), which is ~30 for your test data.
  • A: Subtract the baseline from the maximum y-value: 3630 - 30 = 3600.
  • K: Estimate using a midpoint in your data. For example, at x=100, y=851:
    • 851 ≈ 3600*exp(-K*100) + 30
    • Solve for K: K ≈ -ln((851-30)/3600)/100 ≈ 0.0148

2. Updated code with initial guesses

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

x = np.array([ 1., 4., 9., 16., 25., 36., 49., 64., 81., 100., 121., 144., 169., 196., 225., 256., 289., 324., 361., 400., 441., 484., 529., 576., 625., 676., 729., 784., 841., 900., 961., 1024., 1089., 1156., 1225., 1296., 1369., 1444., 1521., 1600., 1681., 1764., 1849., 1936., 2025., 2116., 2209., 2304., 2401., 2500., 2601., 2704., 2809., 2916., 3025., 3136., 3249., 3364., 3481., 3600., 3721., 3844., 3969., 4096., 4225., 4356., 4489., 4624., 4761., 4943.])
y = np.array([3630., 2590., 2063., 1726., 1484., 1301., 1155., 1036., 936., 851., 778., 714., 657., 607., 562., 521., 485., 451., 421., 390., 362., 336., 312., 293., 279., 265., 253., 241., 230., 219., 209., 195., 183., 171., 160., 150., 142., 134., 127., 120., 114., 108., 102., 97., 91., 87., 83., 80., 76., 73., 70., 67., 64., 61., 59., 56., 54., 51., 49., 47., 45., 43., 41., 40., 38., 36., 35., 33., 31., 30.])

def model_func(x, A, K, C):
    return A * np.exp(-K * x) + C

# Calculate initial guesses based on data
initial_C = np.min(y)
initial_A = np.max(y) - initial_C
# Estimate K using x=100 as a reference point
log_term = np.log((851 - initial_C)/initial_A)
initial_K = -log_term / 100
initial_guess = [initial_A, initial_K, initial_C]

# Fit with initial guess (increase maxfev if needed)
opt_parms, parm_cov = curve_fit(model_func, x, y, p0=initial_guess, maxfev=10000)
A, K, C = opt_parms

# Generate fitted values
fit_y = model_func(x, A, K, C)

# Visualize results
plt.clf()
plt.title('Decay Data & Fitted Curve')
plt.plot(x, y, 'r.', label='Actual Data')
plt.plot(x, fit_y, 'b-', label='Fitted Function:\n $y = %0.2f e^{-%0.6f x} + %0.2f$' % (A, K, C))
plt.legend(bbox_to_anchor=(1.02, 1), loc='upper left', fancybox=True, shadow=True)
plt.xlabel('x')
plt.ylabel('y')
plt.tight_layout()
plt.show()

# Example: Apply to new data
new_x = np.array([5000, 6000, 7000])
new_y_pred = model_func(new_x, A, K, C)
print("Predicted values for new x:", new_y_pred)

3. For datasets with x up to 1e6: Scale your x-values

When x gets as large as 1,000,000, even small K values can make exp(-K*x) underflow or cause numerical issues. Fix this by scaling x (e.g., divide by 1000):

# Scale x to a smaller range
x_scaled = x / 1000

# Adjust model to use scaled x
def model_func_scaled(x_scaled, A, K, C):
    return A * np.exp(-K * x_scaled) + C

# Adjust initial guess for K (multiply by 1000 to match scaling)
initial_guess_scaled = [initial_A, initial_K * 1000, initial_C]

# Fit scaled data
opt_parms_scaled, _ = curve_fit(model_func_scaled, x_scaled, y, p0=initial_guess_scaled)

# Predict new data (remember to scale new x too!)
new_x = np.array([100000, 500000, 1000000])
new_x_scaled = new_x / 1000
new_y_pred = model_func_scaled(new_x_scaled, *opt_parms_scaled)

Final Notes

  • The model you chose is absolutely correct for your exponential decay data.
  • Always provide reasonable initial guesses for curve_fit—it drastically improves fitting accuracy and stability.
  • For large x ranges, scaling is a simple way to avoid numerical overflow/underflow issues.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:16:25