Scipy优化中使用数组型参数时如何避免序列赋值错误?
解决Scipy Minimize中数组型参数的优化问题
这个错误的核心原因很明确:Scipy的minimize函数要求初始参数必须是一维扁平数组,它无法直接处理包含嵌套数组的参数列表。你之前把数组M和theta直接放进params0里,导致numpy在尝试将其转换为数组时遇到了嵌套序列,触发了ValueError。
下面是具体的解决方案,我们只需要做两步:将所有参数扁平化为一维数组,然后在目标函数里重新拆分回原来的标量和数组结构。
修改后的完整代码
import pandas as pd import numpy as np from scipy.integrate import odeint from scipy.optimize import minimize def f(yvec, t, a, b, c, d, M, theta): # the system of ODEs to be solved x, y = yvec dydt = [ a*x - b*y**2 + 1, -c*x - d*x*y + np.sum(M * np.cos(theta*t)) ] return dydt ni = 3 # the number of periodic forcing functions to add to the DE system M_initial = 0.56*np.random.rand(ni) # the initial amplitudes of forcing functions theta_initial = np.pi/6*np.arange(ni) # the initial coefficients of the forcing functions # 1. 将所有参数扁平化为一维数组:标量 + 数组元素依次排列 params0_flat = np.concatenate([ [0.75, 0.23, 1.0, 0.2], # 标量参数a,b,c,d M_initial.flatten(), # M的元素 theta_initial.flatten() # theta的元素 ]) # grabbing the data to be used later data = pd.read_csv('data.csv') y_data = data['Y'] N = y_data.shape[0] #20 t = np.linspace(0, N, N) # array of t values to integrate over yvec0 = [0.3, 0.34] # initial conditions for x and y respectively def norm_residual(params, *args): """ Computes the L^2 norm of the residual of y and the data (y as defined above). Input: params = 一维扁平数组,包含所有优化参数 args = other arguments to pass into the function f or to use to compute the residual. Output: err = L^2 error of the solution vector (scalar). """ data, yvec0, t = args ni = 3 # 和之前定义的ni一致 # 2. 将扁平参数拆分回原来的标量和数组 a, b, c, d = params[:4] M = params[4:4+ni] theta = params[4+ni:] sol = odeint(f, yvec0, t, args=(a, b, c, d, M, theta)) x = sol[:, 0]; y = sol[:, 1] res = data - y err = np.linalg.norm(res, 2) return err # 现在可以正常调用minimize了 p_min = minimize(norm_residual, params0_flat, args=(y_data, yvec0, t)) print(p_min) # 如果需要提取优化后的M和theta: optimized_params = p_min.x optimized_M = optimized_params[4:4+ni] optimized_theta = optimized_params[4+ni:] print("优化后的M:", optimized_M) print("优化后的theta:", optimized_theta)
关键说明
- 参数扁平化:我们用
np.concatenate把标量列表和数组的扁平版本合并成一个一维数组,这样minimize就能正确识别所有参数为连续的优化变量。 - 参数拆分:在目标函数内部,我们根据参数的原始结构,从扁平数组中切片拆分出标量
a,b,c,d和数组M,theta,完全不影响原ODE函数的逻辑。 - 扩展性:如果后续需要调整
ni的数值,只需要修改ni变量,切片逻辑会自动适配,不需要硬编码索引。
这个方法不仅解决了你的错误,还完全保留了让minimize自动优化数组型参数的需求,是处理这类问题的标准做法。
内容的提问来源于stack exchange,提问作者BRz
相关产品推荐
相关产品推荐

