使用缩放器进行衍生检查
Derivative check with scalers
我有一个问题,我想缩放设计变量。我已经添加了定标器,但我想检查导数以确保它正在执行我希望它执行的操作。有没有办法检查缩放导数?我曾尝试使用 check_total_derivatives() 但无论我为 scaler 设置什么值,导数都是完全相同的:
from openmdao.api import Component, Group, Problem, IndepVarComp, ExecComp
from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver
class Scaling(Component):
def __init__(self):
super(Scaling, self).__init__()
self.add_param('x', shape=1)
self.add_output('y', shape=1)
def solve_nonlinear(self, params, unknowns, resids):
unknowns['y'] = 1000. * params['x']**2 + 2
def linearize(self, params, unknowns, resids):
J = {}
J['y', 'x'] = 2000. * params['x']
return J
class ScalingGroup(Group):
def __init__(self,):
super(ScalingGroup, self).__init__()
self.add('x', IndepVarComp('x', 0.0), promotes=['*'])
self.add('g', Scaling(), promotes=['*'])
p = Problem()
p.root = ScalingGroup()
# p.driver = pyOptSparseDriver()
# p.driver.options['optimizer'] = 'SNOPT'
p.driver.add_desvar('x', lower=0.005, upper=100., scaler=1000)
p.driver.add_objective('y')
p.setup()
p['x'] = 3.
p.run()
total = p.check_total_derivatives()
# Derivative is the same regardless of what the scaler is.
缩放器和加法器的行为是一致的,因此检查导数例程以未缩放的方式给出结果更加直观。
如果您真的想在 NLP 看到缩放后的值并且您正在使用 SNOPT 时查看缩放器产生的影响,您可以添加 SNOPT 的导数检查功能:
p.driver.opt_settings['Verify level'] = 3
SNOPT_print.out 将包含,缩放比例设置为 1:
Column x(j) dx(j) Element no. Row Derivative Difference approxn
1 3.00000000E+00 2.19E-06 Objective 6.00000000E+03 6.00000219E+03 ok
或者如果我们将其更改为 x 缩放器为 1000:
Column x(j) dx(j) Element no. Row Derivative Difference approxn
1 3.00000000E+03 1.64E-03 Objective 6.00000000E+00 6.00000164E+00 ok
所以在 check_total_derivatives 使用的问题的单位中,导数不会改变。但是优化器看到的缩放值正在改变。
另一种准确查看优化器从 calc_gradient 看到的内容的方法是模拟对 calc_gradient 的调用。这不一定很容易弄清楚,但我想我会把它贴在这里以供参考。
print p.calc_gradient(list(p.driver.get_desvars().keys()),
list(p.driver.get_objectives().keys()) + list(p.driver.get_constraints().keys()),
dv_scale=p.driver.dv_conversions,
cn_scale=p.driver.fn_conversions)
我有一个问题,我想缩放设计变量。我已经添加了定标器,但我想检查导数以确保它正在执行我希望它执行的操作。有没有办法检查缩放导数?我曾尝试使用 check_total_derivatives() 但无论我为 scaler 设置什么值,导数都是完全相同的:
from openmdao.api import Component, Group, Problem, IndepVarComp, ExecComp
from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver
class Scaling(Component):
def __init__(self):
super(Scaling, self).__init__()
self.add_param('x', shape=1)
self.add_output('y', shape=1)
def solve_nonlinear(self, params, unknowns, resids):
unknowns['y'] = 1000. * params['x']**2 + 2
def linearize(self, params, unknowns, resids):
J = {}
J['y', 'x'] = 2000. * params['x']
return J
class ScalingGroup(Group):
def __init__(self,):
super(ScalingGroup, self).__init__()
self.add('x', IndepVarComp('x', 0.0), promotes=['*'])
self.add('g', Scaling(), promotes=['*'])
p = Problem()
p.root = ScalingGroup()
# p.driver = pyOptSparseDriver()
# p.driver.options['optimizer'] = 'SNOPT'
p.driver.add_desvar('x', lower=0.005, upper=100., scaler=1000)
p.driver.add_objective('y')
p.setup()
p['x'] = 3.
p.run()
total = p.check_total_derivatives()
# Derivative is the same regardless of what the scaler is.
缩放器和加法器的行为是一致的,因此检查导数例程以未缩放的方式给出结果更加直观。
如果您真的想在 NLP 看到缩放后的值并且您正在使用 SNOPT 时查看缩放器产生的影响,您可以添加 SNOPT 的导数检查功能:
p.driver.opt_settings['Verify level'] = 3
SNOPT_print.out 将包含,缩放比例设置为 1:
Column x(j) dx(j) Element no. Row Derivative Difference approxn
1 3.00000000E+00 2.19E-06 Objective 6.00000000E+03 6.00000219E+03 ok
或者如果我们将其更改为 x 缩放器为 1000:
Column x(j) dx(j) Element no. Row Derivative Difference approxn
1 3.00000000E+03 1.64E-03 Objective 6.00000000E+00 6.00000164E+00 ok
所以在 check_total_derivatives 使用的问题的单位中,导数不会改变。但是优化器看到的缩放值正在改变。
另一种准确查看优化器从 calc_gradient 看到的内容的方法是模拟对 calc_gradient 的调用。这不一定很容易弄清楚,但我想我会把它贴在这里以供参考。
print p.calc_gradient(list(p.driver.get_desvars().keys()),
list(p.driver.get_objectives().keys()) + list(p.driver.get_constraints().keys()),
dv_scale=p.driver.dv_conversions,
cn_scale=p.driver.fn_conversions)