Scipy.optimize.minimize目标函数ValueError [英] Scipy.optimize.minimize objective function ValueError

查看:599
本文介绍了Scipy.optimize.minimize目标函数ValueError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用scipy.optimize.minimize来解决一个带有9个自由变量的小型优化问题.我的目标函数基本上是另一个函数的包装器,如果我评估目标函数,则返回类型为'numpy.float32'...这是标量吗?但是,尝试使用最小化功能时出现以下错误:

I am using scipy.optimize.minimize for a small optimization problem with 9 free variables. My objective function is basically a wrapper around another function, and if I evaluate my objective function, the return type is 'numpy.float32'... which is a scalar? However, I am getting the following error when attempting to use the minimize function:

raise ValueError("Objective function must return a scalar")
ValueError: Objective function must return a scalar

不可能将目标函数包装在另一个函数周围吗?其他函数参数是全局声明的,但是如果不可行,我可以将它们硬编码到beam_shear函数中.

Is it not possible to wrap the objective function around another function? The other function arguments are globally declared, but if this is not ok, I can hardcode them into the beam_shear function.

相关代码段:

from numpy import array, shape, newaxis, isnan, arange, zeros, dot, linspace
from numpy import pi, cross, tile, arccos,sin, cos, sum, atleast_2d, asarray, float32, ones

from numpy import sum, reshape
from scipy.optimize import minimize

def normrow(A):
    A = atleast_2d(asarray(A, dtype=float32))
    return (sum(A ** 2, axis=1) ** 0.5).reshape((-1, 1))

def beam_shear(xyz, pt0, pt1, pt2, x):

    # will not work for overlapping nodes...
    s         = zeros((len(xyz), 3))
    xyz_pt0   = xyz[pt0, :]
    xyz_pt1   = xyz[pt1, :]
    xyz_pt2   = xyz[pt2, :]
    e01       = xyz_pt1 - xyz_pt0
    e12       = xyz_pt2 - xyz_pt1
    e02       = xyz_pt2 - xyz_pt0
    trip_norm = cross(e01, e12)
    mu        = 0.5 * (xyz_pt2 - xyz_pt1)
    l01       = normrow(e01)
    l12       = normrow(e12)
    l02       = normrow(e02)
    l_tn      = normrow(trip_norm)
    l_mu      = normrow(mu)
    a         = arccos((l01**2 + l12**2 - l02**2) / (2 * l01 * l12))
    k         = 2 * sin(a) / l02 # discrete curvature
    ex        = trip_norm / tile(l_tn, (1, 3))
    ez        = mu / tile(l_mu, (1, 3))
    ey        = cross(ez, ex)
    kb        = tile(k / l_tn, (1, 3)) * trip_norm
    kx        = tile(sum(kb * ex, 1)[:, newaxis], (1, 3)) * ex
    m         = x * kx
    cma       = cross(m, e01)
    cmb       = cross(m, e12)
    ua        = cma / tile(normrow(cma), (1, 3))
    ub        = cmb / tile(normrow(cmb), (1, 3))
    c1        = cross(e01, ua)
    c2        = cross(e12, ub)
    l_c1      = normrow(c1)
    l_c2      = normrow(c2)
    ms        = sum(m**2, 1)[:, newaxis]
    Sa        = ua * tile(ms * l_c1 / (l01 * sum(m * c1, 1)[:, newaxis]), (1, 3))
    Sb        = ub * tile(ms * l_c2 / (l12 * sum(m * c2, 1)[:, newaxis]), (1, 3))
    Sa[isnan(Sa)] = 0
    Sb[isnan(Sb)] = 0
    s[pt0, :] += Sa
    s[pt1, :] -= Sa + Sb
    s[pt2, :] += Sb
    return s

def cross_section_obj(x):
    s = beam_shear(xyz, pt0, pt1, pt2, x)
    l_s = normrow(s)
    val = sum(l_s)
    return val

xyz = array([[ 0, 0., 0.],
        [ 0.16179067,  0.24172157,  0.],
        [ 0.33933063,  0.47210142,  0.],
        [ 0.53460629,  0.68761389,  0.],
        [ 0.75000537,  0.88293512, 0.],
        [ 0.98816469,  1.04956383, 0.],
        [ 1.25096091,  1.17319961,  0.],
        [ 1.5352774,  1.22977204,  0.],
        [ 1.82109752,  1.18695051,  0.],
        [ 2.06513705, 1.03245579,  0.],
        [ 2.23725517,  0.79943842,  0.]])

pt0 = array([0, 1, 2, 3, 4, 5, 6, 7, 8])
pt1 = array([1, 2, 3, 4, 5, 6, 7, 8, 9])
pt2 = array([2, 3, 4, 5, 6, 7, 8, 9, 10])
EIx = (ones(len(pt1)) * 12.75).reshape(-1, 1)

bounds = []
for i in range(len(EIx)):
    bounds.append((EIx[i][0], EIx[i][0] * 100))


print(type(cross_section_obj(EIx)))
res = minimize(cross_section_obj, EIx, method='SLSQP', bounds=bounds)

如前所述:

print(type(cross_section_obj(EIx)))

返回:

<type 'numpy.float32'>

EIx是用于优化的一组初始值,它是形状(9,1)的数组.

EIx is the set of initial values for the optimization, which is an array of shape (9, 1).

推荐答案

您可能希望查看

You may want to look at Utilizing scipy.optimize.minimize with multiple variables of different shapes. What is important to understand is that if you want to use minimize with arrays, you should pass in the flattened version and then reshape. For that reason I always include the desired shape as one of the arguments to the minimize function. In your case I would do something like so:

def cross_section_obj(x, *args):
    xyz, pt0, pt1, pt2, shape = args
    x = x.reshape(shape)
    s = beam_shear(xyz, pt0, pt1, pt2, x)
    l_s = normrow(s)
    val = sum(l_s)
    return val

然后您的minimize调用将发生如下变化:

Then your minimize call would change like so:

res = minimize(cross_section_obj, EIx.flatten(), method='SLSQP',
               bounds=bounds, args=(xyz, pt0, pt1, pt2, EIx.shape))

这篇关于Scipy.optimize.minimize目标函数ValueError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆