如何在scipy.curve_fit中使用多组初始猜测值进行模型拟合?
Hey there! Let's tackle your curve fitting problem—dealing with 10 free parameters that are super sensitive to initial guesses is definitely tricky, especially when you're aiming for a global minimum instead of getting stuck in local ones. Here's a breakdown of your options:
1. First: Know the Limitation of curve_fit
First off, scipy.optimize.curve_fit uses the Levenberg-Marquardt algorithm by default (or Trust-Region Reflective if bounds are set), which is a local optimizer. That means it starts at your initial guess and converges to the nearest minimum—it has no built-in parameter to automatically test multiple initial guesses and pick the best global result. So you'll need to pair it with other tools, or switch to a global optimization method.
2. Best Option: Use a Global Optimizer First, Then Refine with curve_fit
Your best bet is to use a global optimization algorithm to find a strong initial guess, then feed that into curve_fit to polish the result. Scipy has a few great options for this:
Example with differential_evolution
This algorithm searches the entire parameter space globally without needing a good starting point. Here's how to use it:
import numpy as np from scipy.optimize import curve_fit, differential_evolution # Define your 10-parameter model def model(x, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9): # Replace with your actual model equation return p0*x**9 + p1*x**8 + p2*x**7 + p3*x**6 + p4*x**5 + p5*x**4 + p6*x**3 + p7*x**2 + p8*x + p9 # Your data x_data = np.linspace(0, 10, 100) y_data = model(x_data, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + np.random.normal(0, 50, size=len(x_data)) # Define a residual function for the global optimizer (it minimizes the sum of squared residuals) def residual(params): return np.sum((model(x_data, *params) - y_data)**2) # Set bounds for each parameter (critical for global optimizers to narrow the search space) # Adjust these based on what you know about your parameters param_bounds = [(-10, 10)] * 10 # Example: each parameter between -10 and 10 # Run global optimization to find a good initial guess global_result = differential_evolution(residual, param_bounds) best_initial_guess = global_result.x # Now refine with curve_fit popt, pcov = curve_fit(model, x_data, y_data, p0=best_initial_guess) print("Final optimized parameters:", popt)
Alternative: basinhopping
This is another global optimizer that combines local optimization with random jumps to escape local minima. It works well if you have a rough idea of parameter ranges and want a balance between global search speed and precision.
3. Testing Multiple Initial Guesses (If You Must)
If you have a small set of candidate values for each parameter, you can generate all combinations and test them one by one. Warning: For 10 parameters, even 2 candidates per parameter gives 2^10 = 1024 combinations—this gets computationally expensive fast. Use this only if your candidate sets are tiny.
Here's how to do it with itertools.product:
import itertools # Example candidate initial values for each parameter (keep this small!) candidates = [ [0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10] ] best_residual = np.inf best_params = None # Iterate through all combinations for guess in itertools.product(*candidates): try: popt, pcov = curve_fit(model, x_data, y_data, p0=guess) current_residual = np.sum((model(x_data, *popt) - y_data)**2) if current_residual < best_residual: best_residual = current_residual best_params = popt except RuntimeError: # Skip fits that fail to converge continue print("Best parameters from grid search:", best_params)
4. Bonus: Simplify Your Model If Possible
10 free parameters is a lot—your model might be overfitting the data, which can also make fitting unstable. Take a step back: do you really need all 10 parameters? Can you constrain some parameters based on domain knowledge, or simplify the model structure? This will make fitting easier and more reliable.
内容的提问来源于stack exchange,提问作者Stefano

