OpenMDAO:求解器收敛到非最佳点
OpenMDAO: Solver converging to non-optimal point
我试图了解 OpenMDAO 优化算法的局限性。特别是我设置了以下简单示例:
from openmdao.api import Problem, ScipyOptimizeDriver, ExecComp, IndepVarComp, ExplicitComponent
class AddComp(ExplicitComponent):
def setup(self):
self.add_input("x")
self.add_input("y")
self.add_output("obj")
def compute(self, inputs, outputs):
outputs['obj'] = inputs["x"] + inputs["y"]
# build the model
prob = Problem()
indeps = prob.model.add_subsystem('indeps', IndepVarComp())
indeps.add_output('x', 3.0)
indeps.add_output('y', -4.0)
prob.model.add_subsystem("simple", AddComp())
prob.model.connect('indeps.x', 'simple.x')
prob.model.connect('indeps.y', 'simple.y')
# setup the optimization
prob.driver = ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.model.add_design_var('indeps.x', lower=-50, upper=50)
prob.model.add_design_var('indeps.y', lower=-50, upper=50)
prob.model.add_objective('simple.obj')
prob.setup()
prob.run_driver()
# minimum value
print(prob['simple.obj'])
# location of the minimum
print(prob['indeps.x'])
print(prob['indeps.y'])
打印输出为:
Optimization terminated successfully. (Exit mode 0)
Current function value: -1.0
Iterations: 1
Function evaluations: 1
Gradient evaluations: 1
Optimization Complete
-----------------------------------
[-1.]
[ 3.]
[-4.]
然而,最佳解决方案当然是让 x=y=-50。怎么找不到这个解决方案?
出于某种原因,我想到驱动程序应该为凸问题找到正确的解决方案。但我意识到这听起来像是对求解器局限性的粗略总结。有人可以指出可以通过哪些方法解决哪些问题的解释吗?
这里发生的事情是 OpenMDAO 没有计算优化器的 objective 梯度,因为您必须显式声明部分。
将以下内容添加到组件的设置方法中将声明部分的常量值(在这种情况下我们不需要 compute_partials 方法,因为 objective 是一个线性函数输入的,因此部分是恒定的)。
self.declare_partials(of='obj', wrt='x', val=1.0)
self.declare_partials(of='obj', wrt='y', val=1.0)
或者,您可以告诉 OpenMDAO 通过有限差分或复步计算组件的所有部分:
self.declare_partials(of='*', wrt='*', method='cs')
其中方法是 'cs' 或 'fd' 之一。
通过该更改,找到了预期的最佳值:
Optimization terminated successfully. (Exit mode 0)
Current function value: -99.99999999983521
Iterations: 7
Function evaluations: 7
Gradient evaluations: 7
Optimization Complete
-----------------------------------
[-100.]
[-50.]
[-50.]
我试图了解 OpenMDAO 优化算法的局限性。特别是我设置了以下简单示例:
from openmdao.api import Problem, ScipyOptimizeDriver, ExecComp, IndepVarComp, ExplicitComponent
class AddComp(ExplicitComponent):
def setup(self):
self.add_input("x")
self.add_input("y")
self.add_output("obj")
def compute(self, inputs, outputs):
outputs['obj'] = inputs["x"] + inputs["y"]
# build the model
prob = Problem()
indeps = prob.model.add_subsystem('indeps', IndepVarComp())
indeps.add_output('x', 3.0)
indeps.add_output('y', -4.0)
prob.model.add_subsystem("simple", AddComp())
prob.model.connect('indeps.x', 'simple.x')
prob.model.connect('indeps.y', 'simple.y')
# setup the optimization
prob.driver = ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.model.add_design_var('indeps.x', lower=-50, upper=50)
prob.model.add_design_var('indeps.y', lower=-50, upper=50)
prob.model.add_objective('simple.obj')
prob.setup()
prob.run_driver()
# minimum value
print(prob['simple.obj'])
# location of the minimum
print(prob['indeps.x'])
print(prob['indeps.y'])
打印输出为:
Optimization terminated successfully. (Exit mode 0)
Current function value: -1.0
Iterations: 1
Function evaluations: 1
Gradient evaluations: 1
Optimization Complete
-----------------------------------
[-1.]
[ 3.]
[-4.]
然而,最佳解决方案当然是让 x=y=-50。怎么找不到这个解决方案?
出于某种原因,我想到驱动程序应该为凸问题找到正确的解决方案。但我意识到这听起来像是对求解器局限性的粗略总结。有人可以指出可以通过哪些方法解决哪些问题的解释吗?
这里发生的事情是 OpenMDAO 没有计算优化器的 objective 梯度,因为您必须显式声明部分。
将以下内容添加到组件的设置方法中将声明部分的常量值(在这种情况下我们不需要 compute_partials 方法,因为 objective 是一个线性函数输入的,因此部分是恒定的)。
self.declare_partials(of='obj', wrt='x', val=1.0)
self.declare_partials(of='obj', wrt='y', val=1.0)
或者,您可以告诉 OpenMDAO 通过有限差分或复步计算组件的所有部分:
self.declare_partials(of='*', wrt='*', method='cs')
其中方法是 'cs' 或 'fd' 之一。
通过该更改,找到了预期的最佳值:
Optimization terminated successfully. (Exit mode 0)
Current function value: -99.99999999983521
Iterations: 7
Function evaluations: 7
Gradient evaluations: 7
Optimization Complete
-----------------------------------
[-100.]
[-50.]
[-50.]