如何为未缩放模型(使用ResponseSurface组件)定义局部?

时间:2019-01-11 14:51:23

标签: python optimization openmdao

我正在尝试对包含MetaModelUnstructuredComps(MMUC)的大型模型进行优化,其中使用ReponseSurfaces估算输出。我已经先手动创建了此模型,并且可以正常工作。但是,在该模型中,所有变量都已缩放(也包括响应面和其他组件的输入和输出)。 MMUC的分部使用默认设置的有限差分完成。在第二种实现方式(使用OpenLEGO软件包自动构建)中,组件的输入和输出(代理模型,约束等)没有缩放(尽管使用ref为驱动程序缩放了设计变量)和ref0自变量和约束+目标也在其等式内进行缩放。当我尝试优化此模型(pyOptSparse/SLSQP)时,优化不会成功,并且很难满足几个相等性约束。有趣的是,当我在模型上使用approx_totals(step_calc='rel')时,优化就可以了。这给我的印象是,计算和组合的部分出现了问题。

因此,我尝试使用compute_totals()来调试此问题,以查看优化开始时的总导数。以下是两个响应FRGc.WE的一些典型值:

    of / wrt      | approx_totals  | partials   |
    ---------------------------------------------
    FR / w_WE       -2824914,296     3166,669425
    FR / w_ESF      -7039070,86     -3447,735199
    FR / D          -1416,834424     1,718097909
    FR / w_L        -1594560,102     11755399102
    FR / ESF        -10741467,19    -71835372264
    FR / w_D        -305835126,1     190116092,9
    FR / h          -132,8664739    -1053392,711
    FR / Theta      -7663550,5       76607039579
    FR / w_Theta    -2458516,552     42170,96747
    FR / M          -5692867,582    -1,02E+11
    FR / Lambda     -114534,707      2831614491
    FR / L          -176,6461801     728,0673131
    FR / WE         -833,5583125     3240,452002
    FR / tc         -132833949,9    -17828405236
    FR / w_WT       -2606083,221     99243,27639
    FR / WT         -176,646275      1663865,719
    FR / AR         -3220216,113    -3,03E+11
    FR / Sref       -5339,233451     340740598,7
    Gc.WE / w_WE    -354442,2873    -10,94512505
    Gc.WE / w_ESF   -883192,9447    -7,231199285
    Gc.WE / D       -177,7706417     0,2982562
    Gc.WE / w_L     -200069,6665     0
    Gc.WE / ESF     -1347733,361     0
    Gc.WE / w_D     -38373164,66     0
    Gc.WE / h       -16,6709147     -0,689845824
    Gc.WE / Theta   -961539,6393     0
    Gc.WE / w_Theta -308470,3246     0
    Gc.WE / M       -714285,1914     13180,76857
    Gc.WE / Lambda  -14370,66473     0
    Gc.WE / L       -22,16381204     0
    Gc.WE / WE      -104,5865158     1
    Gc.WE / tc      -16666686,96     0
    Gc.WE / w_WT    -326985,5298     0
    Gc.WE / WT      -22,16381204     0
    Gc.WE / AR      -404040,8959     0
    Gc.WE / Sref    -669,9145362     0
---------------------------------------------

令我惊讶的是,approx_totals()的总数并不总是预期的(例如,Gc.WE / D的预期总数为0),但是优化确实可以使用approx_totals()进行。另外,在优化结束时,这些总数等于或接近零,因此似乎可以正确处理。根据局部变量确定的总数更符合我的期望(至少为0和1),但是优化无法正确运行。

很遗憾,我无法在此处共享完整的代码。我正在研究一个小的工作示例,该示例将显示相同的问题,但到目前为止尚未找到。只是想把我的问题放在这里,看看是否有任何建议。

我希望无论有没有approx_totals(),该模型都可以工作,因为模型中的所有组件都将确定具有有限差异的部分,或者通过分析来提供这些部分(我确信它们是用check_partials()检查后更正)。由于不按比例缩放不同组件的输入,因此我尝试调整step_size方法的fd以匹配输入范围(因此,对于Gc.WE / D,而不是{{ 1}}更改为step_size=1E-6,因为step_size=10000*1E-6在0到20000之间),但无济于事。

您对如何进一步调试此问题有任何建议吗?对于输入范围差异很大的组件,如何最好地声明局部变量?或者,如果使用D的优化有效但不是没有优化,则可能会出现另一个问题,除了局部变量有问题之外?

基于第一个答案的小型示例

approx_totals()

基于此示例,我得到以下日志:

    import numpy as np

    from openmdao.api import Problem, Group, ResponseSurface, IndepVarComp, MetaModelUnStructuredComp

    x_train = np.arange(0., 10.)
    y_train = np.arange(10., 20.)
    z_train = x_train**2 + y_train**2

    p = Problem()
    p.model = m = Group()

    params = IndepVarComp()
    params.add_output('x', val=0.)
    params.add_output('y', val=0.)

    m.add_subsystem('params', params, promotes=['*'])

    sm = MetaModelUnStructuredComp(default_surrogate=ResponseSurface())
    sm.add_input('x', val=0.)
    sm.add_input('y', val=0.)
    sm.add_output('z', val=0.)

    sm.options['train:x'] = x_train
    sm.options['train:y'] = y_train
    sm.options['train:z'] = z_train

    # With or without the line below does not matter
    # Only when method is set to fd, then RuntimeWarning disappears
    sm.declare_partials('*', '*', method='exact')

    m.add_subsystem('sm', sm, promotes=['*'])

    m.add_design_var('x', lower=0., upper=10.)
    m.add_design_var('y', lower=0., upper=10.)
    m.add_objective('z')

    p.setup()

    p['x'] = 5.
    p['y'] = 12.

    p.run_model()

    print('\nSM-value z: {}'.format(float(p['z'])))
    print('theoretical z: {}'.format(float(p['x']**2 + p['y']**2)))

    totals = p.compute_totals()

    print('\nSM-value z wrt x: {}'.format(totals[('sm.z', 'params.x')][0][0]))
    print('theoretical value z wrt x: {}'.format(2*p['x'][0]))
    print('\nSM-value z wrt y: {}'.format(totals[('sm.z', 'params.y')][0][0]))
    print('theoretical value z wrt y: {}'.format(2*p['y'][0]))

第一条RunTimeWarning消息引起了我的困惑。为了摆脱它,我用/Users/imcovangent/Documents/PhD/Software/OpenMDAO/openmdao/components/meta_model_unstructured_comp.py:287: RuntimeWarning:Because the MetaModelUnStructuredComp 'sm' uses a surrogate which does not define a linearize method, OpenMDAO will use finite differences to compute derivatives. Some of the derivatives will be computed using default finite difference options because they were not explicitly declared. The derivatives computed using the defaults are: sm.z, sm.x sm.z, sm.y SM-value z: 169.213661944 theoretical z: 169.0 SM-value z wrt x: 10.0415292063 theoretical value z wrt x: 10.0 SM-value z wrt y: 23.9584707937 theoretical value z wrt y: 24.0 /usr/local/lib/python2.7/site-packages/scipy/linalg/basic.py:1018: RuntimeWarning: internal gelsd driver lwork query error, required iwork dimension not returned. This is likely the result of LAPACK bug 0038, fixed in LAPACK 3.2.2 (released July 21, 2010). Falling back to 'gelss' driver. warnings.warn(mesg, RuntimeWarning) 声明了partials,但再次查看它似乎只是发出警告,但实际上它是使用替代模型的method=fd方法。因此,警告对于linearize代理模型是不正确的。

1 个答案:

答案 0 :(得分:0)

我的第一个建议是在您的MetaModelUnstructured实例周围放置一个组,然后特别对该组设置roximate_totals方法。这将使您能够隔离该特定组件。如果您可以根据它使它工作/不工作,则其100%确认它是元模型,而不是其他一些带有不良局部的组件。您自己使用手动编码的元模型与OpenMDAO组件进行的测试似乎肯定暗示着问题所在……但是再进行一次健全性检查就可以了。

某些替代模型确实具有解析导数,但有些则没有,然后使用FD。听起来您正在使用ResponseSurface代理,它确实提供了解析导数。但是在该实现中可能存在一个错误。如果存在错误,并且您在外观上没有看到任何东西出现在check_partials中,那么我建议采用最终的优化结果(或接近它的某个点)并将其设置为初始条件,然后调用单个{ {1}},然后再调用run_model()。如果以上建议的健全性检查证明问题出在您的MetaModel组件上。 FY您可以专门指定元模型组件的名称