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



我正在尝试运行一个包含MetaModelUnstructuredComps(MMUC)的大型模型的优化,其中使用ReponseSurfaces估计输出。我已经先手动创建了这个模型,它可以按预期工作。然而,在该模型中,所有变量都是按比例缩放的(还有响应面和其他组件的输入和输出)。MMUC的局部使用具有默认设置的有限差分进行。在第二个实现中(使用OpenLEGO包自动构建),组件的输入和输出(代理模型、约束等)没有缩放(尽管使用refref0自变量为驱动器缩放设计变量,并且约束+目标也在其方程中缩放)。当我试图优化这个模型(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()检查后,我确信它们是正确的)。由于不同组件的输入没有缩放,我试图调整fd方法的step_size以匹配输入的范围(因此,对于Gc.WE / D,而不是step_size=1E-6,它被更改为step_size=10000*1E-6,因为D在0和20000之间),但没有成功。

你对如何进一步调试这个问题有什么建议吗?对于输入范围大不相同的组件,如何最好地声明分部?或者,如果使用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]))

基于这个例子,我得到了以下日志:

/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)

第一条RunTimeWarning消息引起了我的困惑。为了摆脱它,我用method=fd声明了分部,但再次查看它,它似乎只是发出警告,但实际上它使用了代理模型的linearize方法。因此,该警告对于ResponseSurface代理模型是不正确的。

我的第一个建议是在MetaModelUnstructured实例周围放置一个组,然后在该组上特别设置approx_totals方法。这将允许您隔离该特定组件。如果你能让它在这个基础上工作/不工作,那么它100%确认它是元模型,而不是其他有坏部分的组件。您自己使用手工编码的元模型与OpenMDAO组件进行的测试似乎肯定意味着问题已经存在。。。但只要再做一次理智检查就好了。

有些代理模型确实有解析导数,但有些没有,然后使用FD。听起来你在使用ResponseSurface代理,它确实提供了分析导数。但也许这个实现中存在一个错误。如果有一个bug,并且在查看时没有在check_partials中显示任何内容,那么我建议将最终优化的结果(或接近它的某个点)设置为初始条件,然后在调用check_partials()之前调用单个run_model()。如果以上建议的健全性检查证明问题出在您的MetaModel组件上。FY您可以指定元模型组件的名称,特别是

最新更新