使用Scipy的differential_evolution函数时遇RuntimeError问题求助
使用Scipy differential_evolution时遇到RuntimeError的解决方法
问题描述
在完成大学课程参数化作业时,用Scipy的differential_evolution拟合五次多项式,出现错误:
RuntimeError: The map-like callable must be of the form f(func, iterable), returning a sequence of numbers the same length as 'iterable'
代码及错误栈如下:
原代码
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import differential_evolution x = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] y = [0.0, 1.8, 2.0, 4.0, 4.0, 6.0, 4.0, 3.6, 3.4, 2.8, 0.0] plt.plot(x, y, 'bo', markersize=3, label='Dados') plt.legend() plt.show() def model_reta(x, c0, c1, c2, c3, c4, c5 ): return c0+c1*x+c2*pow(x,2)+c3*pow(x,3)+c4*pow(x,4)+c5*pow(x,5) def model(params): sol = model_reta(x, params[0], params[1], params[2], params[3], params[4], params[5]) erro = np.linalg.norm(y-sol, 1)/np.linalg.norm(y, 1) return [erro, sol, x] def model_adj(x, args): result = model(x) return result[0] bounds = [(-10, 10),(-10, 10),(-10, 10),(-10, 10),(-10, 10),(-10, 10),] result = differential_evolution(model_adj, bounds, strategy='best1bin', disp=True)
完整错误栈
TypeError Traceback (most recent call last) File c:\Users\filip\AppData\Local\Programs\Python\Python311\Lib\site-packages\scipy\optimize\_differentialevolution.py:1146, in DifferentialEvolutionSolver._calculate_population_energies(self, population) 1145 try: -> 1146 calc_energies = list( 1147 self._mapwrapper(self.func, parameters_pop[0:S]) 1148 ) 1149 calc_energies = np.squeeze(calc_energies) File c:\Users\filip\AppData\Local\Programs\Python\Python311\Lib\site-packages\scipy\_lib\_util.py:360, in _FunctionWrapper.__call__(self, x) 359 def __call__(self, x): -> 360 return self.f(x, *self.args) TypeError: model_adj() missing 1 required positional argument: 'args' The above exception was the direct cause of the following exception: RuntimeError Traceback (most recent call last) d:\Scripts Python\atividade_integracao_numerica\integracao_numerica.ipynb Cell 9 line 1 13 return result[0] 15 bounds = [(-10, 10),(-10, 10),(-10, 10),(-10, 10),(-10, 10),(-10, 10),] ---> 17 result = differential_evolution(model_adj, bounds, strategy='best1bin', disp=True) 18 ''' 19 print(result.x) 20 erro, sol, x = model(result.x) ... 1156 ) from e 1158 if calc_energies.size != S: 1159 if self.vectorized: RuntimeError: The map-like callable must be of the form f(func, iterable), returning a sequence of numbers the same length as 'iterable'
错误原因
- 目标函数参数不符合要求:
differential_evolution要求目标函数仅接受一个参数(待优化的系数数组),但model_adj定义了两个参数,且参数名x与全局数据变量重名,导致逻辑混淆。 - 冗余返回值干扰优化:
model函数返回了误差、预测值、数据x三个元素,但优化过程只需要误差值作为目标输出,多余返回值破坏了优化逻辑。
修正后的代码
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import differential_evolution # 原始数据,重命名避免与参数混淆 x_data = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] y_data = [0.0, 1.8, 2.0, 4.0, 4.0, 6.0, 4.0, 3.6, 3.4, 2.8, 0.0] plt.plot(x_data, y_data, 'bo', markersize=3, label='Dados') plt.legend() plt.show() # 五次多项式模型,直接接收系数数组 def model_poly(x, coeffs): c0, c1, c2, c3, c4, c5 = coeffs return c0 + c1*x + c2*x**2 + c3*x**3 + c4*x**4 + c5*x**5 # 优化目标函数:仅返回归一化L1误差 def objective_func(coeffs): y_pred = model_poly(x_data, coeffs) return np.linalg.norm(y_data - y_pred, 1) / np.linalg.norm(y_data, 1) # 参数边界 bounds = [(-10, 10)] * 6 # 运行差分进化优化 result = differential_evolution(objective_func, bounds, strategy='best1bin', disp=True) # 输出结果并绘制拟合曲线 print("优化得到的系数:", result.x) y_fit = model_poly(x_data, result.x) plt.plot(x_data, y_data, 'bo', markersize=3, label='Dados') plt.plot(x_data, y_fit, 'r-', label='Ajuste') plt.legend() plt.show()
关键修改说明
- 重命名全局数据变量为
x_data、y_data,避免与函数参数冲突。 - 简化多项式模型函数,直接接收系数数组作为参数,无需逐个拆解。
- 目标函数仅返回误差值,完全符合
differential_evolution的输入要求。 - 移除冗余的中间函数,优化代码结构,逻辑更清晰。
内容的提问来源于stack exchange,提问作者Filipe Vidal
相关产品推荐
相关产品推荐

