Масштабный параболоид и проверка производных

Я удивлен выводом метода check_partial_derivatives(), примененного к проблеме, показанной в моем предыдущем вопросе: Оптимизация параболоидов, требующая масштабирования. Когда я добавляю вызов к этому методу:

from __future__ import print_function
import sys

from openmdao.api import IndepVarComp, Component, Problem, Group, ScipyOptimizer

class Paraboloid(Component):

    def __init__(self):
        super(Paraboloid, self).__init__()

        self.add_param('x', val=0.0)
        self.add_param('y', val=0.0)

        self.add_output('f_xy', val=0.0)

    def solve_nonlinear(self, params, unknowns, resids):

        x = params['x']
        y = params['y']

        #unknowns['f_xy'] = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0
        unknowns['f_xy'] = (1000.*x-3.)**2 + (1000.*x)*(0.01*y) + (0.01*y+4.)**2 - 3.

    def linearize(self, params, unknowns, resids):
        """ Jacobian for our paraboloid."""
        x = params['x']
        y = params['y']
        J = {}

        #J['f_xy', 'x'] = 2.0*x - 6.0 + y
        #J['f_xy', 'y'] = 2.0*y + 8.0 + x
        J['f_xy', 'x'] = 2000000.0*x - 6000.0 + 10.0*y
        J['f_xy', 'y'] = 0.0002*y + 0.08 + 10.0*x

        return J

if __name__ == "__main__":

    top = Problem()

    root = top.root = Group()
    #root.fd_options['force_fd'] = True

    root.add('p1', IndepVarComp('x', 3.0))
    root.add('p2', IndepVarComp('y', -4.0))
    root.add('p', Paraboloid())

    root.connect('p1.x', 'p.x')
    root.connect('p2.y', 'p.y')

    top.driver = ScipyOptimizer()
    top.driver.options['optimizer'] = 'SLSQP'

    top.driver.add_desvar('p1.x', lower=-1000, upper=1000, scaler=1000.)
    top.driver.add_desvar('p2.y', lower=-1000, upper=1000, scaler=0.001)
    top.driver.add_objective('p.f_xy')


    top.setup()
    top.check_partial_derivatives()  # added line
    top.run()


    print('\n')
    print('Minimum of %f found at (%f, %f)' % (top['p.f_xy'], top['p.x'], top['p.y']))

Получаю следующий результат:

Partial Derivatives Check

----------------
Component: 'p'
----------------
  p: 'f_xy' wrt 'x'

    Forward Magnitude : 6.000000e+03
    Reverse Magnitude : 6.000000e+03
         Fd Magnitude : 2.199400e+07

    Absolute Error (Jfor - Jfd) : 2.200000e+07
    Absolute Error (Jrev - Jfd) : 2.200000e+07
    Absolute Error (Jfor - Jrev): 0.000000e+00

    Relative Error (Jfor - Jfd) : 1.000273e+00
    Relative Error (Jrev - Jfd) : 1.000273e+00
    Relative Error (Jfor - Jrev): 0.000000e+00

    Raw Forward Derivative (Jfor)

[[-6000.]]

    Raw Reverse Derivative (Jrev)

[[-6000.]]

    Raw FD Derivative (Jfor)

[[ 21994001.]]
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  p: 'f_xy' wrt 'y'

    Forward Magnitude : 8.000000e-02
    Reverse Magnitude : 8.000000e-02
         Fd Magnitude : 2.200000e+07

    Absolute Error (Jfor - Jfd) : 2.200000e+07
    Absolute Error (Jrev - Jfd) : 2.200000e+07
    Absolute Error (Jfor - Jrev): 0.000000e+00

    Relative Error (Jfor - Jfd) : 1.000000e+00
    Relative Error (Jrev - Jfd) : 1.000000e+00
    Relative Error (Jfor - Jrev): 0.000000e+00

    Raw Forward Derivative (Jfor)

[[ 0.08]]

    Raw Reverse Derivative (Jrev)

[[ 0.08]]

    Raw FD Derivative (Jfor)

[[ 22000000.08]]
Optimization terminated successfully.    (Exit mode 0)
            Current function value: [-27.33333333]
            Iterations: 4
            Function evaluations: 6
            Gradient evaluations: 4
Optimization Complete
-----------------------------------


Minimum of -27.333333 found at (0.006667, -733.333333)

Оптимизация верна (т. Е. Почти наверняка доказывает правильность производных), но результат check_partial_derivatives не показывает согласованных результатов между методами fd и прямым / обратным ходом.


person relf    schedule 25.02.2016    source источник


Ответы (1)


relf

Итак, вы столкнулись с ограничением, которое возникло раньше, а именно: вы не можете рассчитывать производные относительно точки проектирования, пока не запустите свою модель в этой точке. Результаты конечных разностей неверны, потому что модель никогда не запускалась. Чтобы проверить свои частичные данные, вам нужно после запуска переместить check_partial_derivatives в. Кроме того, я всегда комментирую оптимизатор, когда проверяю производные, чтобы проверять производные относительно начальной точки. Когда я сделал эти две вещи, я получил хорошие результаты (см. Код ниже).

top = Problem()

root = top.root = Group()
#root.fd_options['force_fd'] = True

root.add('p1', IndepVarComp('x', 3.0))
root.add('p2', IndepVarComp('y', -4.0))
root.add('p', Paraboloid())

root.connect('p1.x', 'p.x')
root.connect('p2.y', 'p.y')

#top.driver = ScipyOptimizer()
#top.driver.options['optimizer'] = 'SLSQP'

#top.driver.add_desvar('p1.x', lower=-1000, upper=1000, scaler=1000.)
#top.driver.add_desvar('p2.y', lower=-1000, upper=1000, scaler=0.001)
#top.driver.add_objective('p.f_xy')

top.setup()
top.run()
top.check_partial_derivatives()  # added line

print('\n')
print('Minimum of %f found at (%f, %f)' % (top['p.f_xy'], top['p.x'], top['p.y']))

В нашем github есть запрос на возможность запуска check_partial_derivatives без предварительного запуска модели. Я думаю, что это возможно, если мы просто скажем root, что нужно решить_nonlinear, игнорируя драйвер, так что он, вероятно, будет добавлен в какой-то момент.

person Kenneth Moore    schedule 25.02.2016
comment
Спасибо, Кеннет. А пока, может быть, можно было бы добавить предупреждение, если пользователь использует метод, не запустив модель? - person relf; 25.02.2016