Производный чек со скейлерами

У меня проблема с масштабированием проектных переменных. Я добавил масштабатор, но я хочу проверить производную, чтобы убедиться, что она делает то, что я хочу. Есть ли способ проверить масштабированную производную? Я пытался использовать 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.

2 ответа

Решение

Другой способ точно увидеть, что оптимизатор видит в 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)

Скейлеры и сумматоры последовательны в своем поведении, поэтому процедуры проверки производных дают результаты в немасштабированном выражении, чтобы быть более интуитивными.

Если вы действительно хотите увидеть, какое влияние оказывает скалер, когда НЛП видит масштабированное значение и вы используете 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

Или, если мы изменим его на масштабирование х на 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, производная не изменяется. Но масштабированное значение, видимое оптимизатором, меняется.

Другие вопросы по тегам