scipy.optimize.minimize 具有通用数组索引
scipy.optimize.minimize with general array indexing
我想用scipy.optimize.minimize中的方法'COBYLA'解决一个优化问题如下:
test = spopt.minimize(testobj, x_init, method='COBYLA', constraints=cons1)
y = test.x
print 'solution x =', y
但是,由于程序非常大,编写 objective 函数(和约束)的一种可伸缩方法是对参数使用通用索引。例如,如果我可以使用 x['parameter1']
或 x.param1
而不是 x[0]
,那么程序将更易于阅读和调试。我尝试将 x
写成一个对象或 pandas Series
并使用像 x['parameter1']
这样的一般索引,如下所示:
def testobj(x):
return x['a']**2 + x['b'] + 1
def testcon1(x):
return x['a']
def testcon2(x):
return x['b']
def testcon3(x):
return 1 - x['a'] - x['b']
x_init = pd.Series([0.1, 0.1])
x_init.index = ['a','b']
cons1 = ({'type': 'ineq', 'fun': testcon1}, \
{'type': 'ineq', 'fun': testcon2}, \
{'type': 'ineq', 'fun': testcon3})
但是每当我将它传递给 minimize
例程时,它就会抛出一个错误:
return x['a']**2 + x['b'] + 1
ValueError: field named a not found
如果我使用普通的 numpy 数组,它工作得很好。也许我做的不对,但这是我必须使用 numpy 数组而不是任何其他数据结构的最小化函数的限制吗? this topic 上的 scipy 文档提到初始猜测必须是 ndarray,但我很好奇例程如何调用参数,因为对于 pandas Series
调用变量 x[0]
或 x['a']
是等价的。
如您所见,scipy 优化使用 numpy 数组作为输入,而不是 pandas 系列。当您使用 pandas 系列进行初始化时,它会有效地将其转换为数组,因此您无法再按名称访问字段。
可能最简单的方法就是创建一个函数,在您每次调用它们时重新包装参数;例如:
def make_series(params):
return pd.Series(params, index=['a', 'b'])
def testobj(x):
x = make_series(x)
return x['a']**2 + x['b'] + 1
def testcon1(x):
x = make_series(x)
return x['a']
def testcon2(x):
x = make_series(x)
return x['b']
def testcon3(x):
x = make_series(x)
return 1 - x['a'] - x['b']
x_init = make_series([1, 1])
test = spopt.minimize(testobj, x_init, method='COBYLA', constraints=cons1)
print('solution x =', test.x)
# solution x = [ 1.38777878e-17 0.00000000e+00]
我想用scipy.optimize.minimize中的方法'COBYLA'解决一个优化问题如下:
test = spopt.minimize(testobj, x_init, method='COBYLA', constraints=cons1)
y = test.x
print 'solution x =', y
但是,由于程序非常大,编写 objective 函数(和约束)的一种可伸缩方法是对参数使用通用索引。例如,如果我可以使用 x['parameter1']
或 x.param1
而不是 x[0]
,那么程序将更易于阅读和调试。我尝试将 x
写成一个对象或 pandas Series
并使用像 x['parameter1']
这样的一般索引,如下所示:
def testobj(x):
return x['a']**2 + x['b'] + 1
def testcon1(x):
return x['a']
def testcon2(x):
return x['b']
def testcon3(x):
return 1 - x['a'] - x['b']
x_init = pd.Series([0.1, 0.1])
x_init.index = ['a','b']
cons1 = ({'type': 'ineq', 'fun': testcon1}, \
{'type': 'ineq', 'fun': testcon2}, \
{'type': 'ineq', 'fun': testcon3})
但是每当我将它传递给 minimize
例程时,它就会抛出一个错误:
return x['a']**2 + x['b'] + 1
ValueError: field named a not found
如果我使用普通的 numpy 数组,它工作得很好。也许我做的不对,但这是我必须使用 numpy 数组而不是任何其他数据结构的最小化函数的限制吗? this topic 上的 scipy 文档提到初始猜测必须是 ndarray,但我很好奇例程如何调用参数,因为对于 pandas Series
调用变量 x[0]
或 x['a']
是等价的。
如您所见,scipy 优化使用 numpy 数组作为输入,而不是 pandas 系列。当您使用 pandas 系列进行初始化时,它会有效地将其转换为数组,因此您无法再按名称访问字段。
可能最简单的方法就是创建一个函数,在您每次调用它们时重新包装参数;例如:
def make_series(params):
return pd.Series(params, index=['a', 'b'])
def testobj(x):
x = make_series(x)
return x['a']**2 + x['b'] + 1
def testcon1(x):
x = make_series(x)
return x['a']
def testcon2(x):
x = make_series(x)
return x['b']
def testcon3(x):
x = make_series(x)
return 1 - x['a'] - x['b']
x_init = make_series([1, 1])
test = spopt.minimize(testobj, x_init, method='COBYLA', constraints=cons1)
print('solution x =', test.x)
# solution x = [ 1.38777878e-17 0.00000000e+00]