使用scipy中differential_evolution()时遇到TypeError错误的求助
你这个错误其实是两个小问题叠加出来的,咱们一个个说清楚怎么解决:
首先最直接的原因是参数顺序搞错了!scipy的differential_evolution函数的位置参数有严格顺序:第一个是目标函数,第二个必须是bounds(变量边界),而x0是可选的关键字参数,不能放在位置参数里。你现在把x0插到了func和bounds之间,导致原本该传给bounds的位置被x0占了,后面的bounds被当成了args参数传入,再加上你又显式写了args=(...),这就造成args被赋值了两次,直接触发了那个TypeError。
其次还有个类方法的参数绑定问题:你的loss_function是类的成员方法,第一个参数是self。当你直接传self.loss_function给differential_evolution时,这个方法已经绑定了self,但differential_evolution期望目标函数的第一个参数是待优化的变量x,这会导致参数传递混乱,就算解决了第一个错误,后面大概率还会报参数不匹配的问题。
具体修复步骤:
修正参数顺序+拼写错误
先把参数顺序改对,把x0放到关键字参数的位置,同时注意你代码里的streategy拼写错了,应该是strategy,这个也得改:res = differential_evolution( self.loss_function, bounds, # 第二个位置参数必须是bounds args=(input_series, ilt, bhpgrad, q_obs), strategy='best1bin', maxiter=1000, popsize=15, disp=True, tol=1e-6, x0=x0 # x0作为关键字参数传入 )解决类方法的参数冲突
这里给你两种简单的解决方式,选哪种都可以:方式一:用lambda包装目标函数
直接用lambda把self和那些常量参数都绑定好,这样就不用再通过args传递了,代码更直观:res = differential_evolution( lambda x: self.loss_function(x, input_series, ilt, bhpgrad, q_obs), bounds, strategy='best1bin', maxiter=1000, popsize=15, disp=True, tol=1e-6, x0=x0 )方式二:把loss_function改成静态方法
如果你的损失函数不需要用到类的其他属性或方法,可以给它加上@staticmethod装饰器,这样就不需要self参数了:@staticmethod def loss_function(x, input_series, ilt, bhpgrad, q_obs): # 你的损失函数逻辑代码 pass这种情况下,你就可以正常用
args传递参数,同时保持参数顺序正确:res = differential_evolution( self.loss_function, bounds, args=(input_series, ilt, bhpgrad, q_obs), strategy='best1bin', maxiter=1000, popsize=15, disp=True, tol=1e-6, x0=x0 )
先把这两个问题解决,你的错误应该就能消失了。
备注:内容来源于stack exchange,提问作者Murali

