使用缩放器进行衍生检查

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)