如何在 OpenMDAO 中处理大小为 2D 的参数?
How to handle params of size 2D in OpenMDAO?
我有一个二维数组参数。它可以很好地获得正确的输出,但是当我尝试对梯度进行任何操作(例如优化或 check_total_derivatives 时,我会遇到尺寸错误。我想知道处理 2D 大小的参数的最佳方法是什么。这是一个示例代码:
import numpy as np
from openmdao.api import Group, Problem, Component, IndepVarComp, ExecComp
class C1(Component):
def __init__(self, n):
super(C1, self).__init__()
self.add_param('grid', val=np.zeros((n, n)))
self.add_output('x', shape=1)
self.n = n
def solve_nonlinear(self, params, unknowns, resids):
x = 0
for i in range(self.n):
for j in range(self.n):
x += params['grid'][i][j]
unknowns['x'] = x
def linearize(self, params, unknowns, resids):
J = {}
J['x', 'grid'] = np.ones((self.n, self.n))
return J
class Group1(Group):
def __init__(self, n):
super(Group1, self).__init__()
self.add('grid', IndepVarComp('grid', np.zeros((n, n))), promotes=['*'])
self.add('c1', C1(n), promotes=['*'])
self.add('obj_cmp', ExecComp('obj = -x', x=1.0), promotes=['*'])
n = 3
p = Problem()
p.root = Group1(n)
p.setup(check=False)
p['grid'] = np.ones((n, n))
p.run()
p.check_total_derivatives()
print p['x']
我收到错误:
ValueError: In component 'c1', the derivative of 'x' wrt 'grid' should have shape '(1, 3)' but has shape '(3, 3)' instead.
我觉得这种情况下的导数应该是大小 (3, 3) 因为这是输入参数的大小。你如何处理二维参数?
当你有一个 2D 变量并且需要构造梯度时,将其展平(按 row-major 顺序)并根据展平版本制定梯度。
你在雅可比矩阵中有一个小错误;它应该看起来像这样:
def linearize(self, params, unknowns, resids):
J = {}
J['x', 'grid'] = np.ones((1, self.n*self.n))
return J
输出x
是长度1,而参数grid
是n乘n,所以它的长度是n*n,所以得到的J应该是1乘9。随着那个变化, 我答对了。
我注意到错误消息中有一个错误。应该说预期的形状是 (1, 9) 而不是 (1, 3)。我会对此进行修复。
我有一个二维数组参数。它可以很好地获得正确的输出,但是当我尝试对梯度进行任何操作(例如优化或 check_total_derivatives 时,我会遇到尺寸错误。我想知道处理 2D 大小的参数的最佳方法是什么。这是一个示例代码:
import numpy as np
from openmdao.api import Group, Problem, Component, IndepVarComp, ExecComp
class C1(Component):
def __init__(self, n):
super(C1, self).__init__()
self.add_param('grid', val=np.zeros((n, n)))
self.add_output('x', shape=1)
self.n = n
def solve_nonlinear(self, params, unknowns, resids):
x = 0
for i in range(self.n):
for j in range(self.n):
x += params['grid'][i][j]
unknowns['x'] = x
def linearize(self, params, unknowns, resids):
J = {}
J['x', 'grid'] = np.ones((self.n, self.n))
return J
class Group1(Group):
def __init__(self, n):
super(Group1, self).__init__()
self.add('grid', IndepVarComp('grid', np.zeros((n, n))), promotes=['*'])
self.add('c1', C1(n), promotes=['*'])
self.add('obj_cmp', ExecComp('obj = -x', x=1.0), promotes=['*'])
n = 3
p = Problem()
p.root = Group1(n)
p.setup(check=False)
p['grid'] = np.ones((n, n))
p.run()
p.check_total_derivatives()
print p['x']
我收到错误:
ValueError: In component 'c1', the derivative of 'x' wrt 'grid' should have shape '(1, 3)' but has shape '(3, 3)' instead.
我觉得这种情况下的导数应该是大小 (3, 3) 因为这是输入参数的大小。你如何处理二维参数?
当你有一个 2D 变量并且需要构造梯度时,将其展平(按 row-major 顺序)并根据展平版本制定梯度。
你在雅可比矩阵中有一个小错误;它应该看起来像这样:
def linearize(self, params, unknowns, resids):
J = {}
J['x', 'grid'] = np.ones((1, self.n*self.n))
return J
输出x
是长度1,而参数grid
是n乘n,所以它的长度是n*n,所以得到的J应该是1乘9。随着那个变化, 我答对了。
我注意到错误消息中有一个错误。应该说预期的形状是 (1, 9) 而不是 (1, 3)。我会对此进行修复。