重构含scipy.optimize.minimize的代码为类时优化不收敛问题排查
问题
我正在整理代码,将原本非结构化的代码重构为独立类。该代码通过优化流出率,使久期结果匹配久期目标,原代码可正常运行但存在全局变量滥用问题。编写对应类实现后,发现scipy.optimize.minimize无法更新outflow参数,导致优化结果无法收敛,且与原代码的res.x结果不同。
原代码:
import scipy.optimize as optimize volume = 100 value = 95 discount_rates = <some dataframe> duration_target = 1.5 initial_guess = 0 def calculate_duration(discount_rates, outflow, volume, value): ... def fun(outflow): duration_outcome = calculate_duration(discount_rates, outflow, volume, value) target = abs(duration_outcome - duration_target) return target def solv(): res = optimize.minimize(fun, initial_guess, method = 'SLSQP', tol=1e-8) return res.x
类实现代码:
import scipy.optimize as optimize class Calculate: def __init__(self, discount_rates, volume, value, duration, initial_guess): self.discount_rates = discount_rates self.volume = volume self.value = value self.duration_target = duration_target self.initial_guess = initial_guess def calculate_duration(self, outflow): ... def fun(self, outflow): duration_outcome = self.calculate_cashflows(outflow) target = abs(duration_outcome - self.duration_target) return target def solv(self): # solution res = optimize.minimize(self.fun, self.initial_guess, method = 'SLSQP', tol=1e-8) return res.x
请问类实现中犯了什么错误?
错误分析
你的类实现存在几个直接导致优化失效的错误:
初始化方法参数与赋值不匹配
__init__的参数是duration,但内部赋值时用了未定义的duration_target,要么会抛出NameError,要么错误复用全局变量,导致目标久期不是你传入的值。
修复方式:将__init__的参数改为duration_target,确保赋值匹配:def __init__(self, discount_rates, volume, value, duration_target, initial_guess): self.discount_rates = discount_rates self.volume = volume self.value = value self.duration_target = duration_target self.initial_guess = initial_guess调用了不存在的方法
fun方法里调用了self.calculate_cashflows(outflow),但类中实际定义的方法是calculate_duration,这会触发AttributeError,导致久期计算失败,优化自然无法收敛。
修复方式:将调用改为self.calculate_duration(outflow)。calculate_duration方法逻辑不一致
原函数需要discount_rates、outflow、volume、value四个参数,而类中的calculate_duration只接收outflow。你需要确保该方法使用实例属性self.discount_rates、self.volume、self.value完成计算,保持和原函数一致的逻辑,否则久期计算结果错误,会让优化方向完全偏离。
内容的提问来源于stack exchange,提问作者t.pellegrom

