【问题标题】:Function returns a vector, how to minimize in via NumPy函数返回一个向量,如何通过 NumPy 最小化
【发布时间】:2014-10-01 19:34:38
【问题描述】:

我正在尝试最小化函数,它返回一个值向量, 这是一个错误:

使用序列设置数组元素

代码:

P = np.matrix([[0.3, 0.1, 0.2], [0.01, 0.4, 0.2], [0.0001, 0.3, 0.5]])  
Ps = np.array([10,14,5])

def objective(x):   
    x = np.array([x])
    res = np.square(Ps - np.dot(x, P)) 
    return res 

def main():
    x = np.array([10, 11, 15])
    print minimize(objective, x, method='Nelder-Mead')

在这些 P、Ps、x 值处,函数返回 [[ 47.45143225 16.81 44.89 ]]

感谢您的建议

UPD(完整追溯)

    Traceback (most recent call last):

  File "<ipython-input-125-9649a65940b0>", line 1, in <module>
    runfile('C:/Users/Roark/Documents/Python Scripts/optimize.py', wdir='C:/Users/Roark/Documents/Python Scripts')

  File "C:\Anaconda\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 585, in runfile
    execfile(filename, namespace)

  File "C:/Users/Roark/Documents/Python Scripts/optimize.py", line 28, in <module>
    main()

  File "C:/Users/Roark/Documents/Python Scripts/optimize.py", line 24, in main
    print minimize(objective, x, method='Nelder-Mead')

  File "C:\Anaconda\lib\site-packages\scipy\optimize\_minimize.py", line 413, in minimize
    return _minimize_neldermead(fun, x0, args, callback, **options)

  File "C:\Anaconda\lib\site-packages\scipy\optimize\optimize.py", line 438, in _minimize_neldermead
    fsim[0] = func(x0)

ValueError: setting an array element with a sequence.

UPD2:函数应该被最小化(Ps是一个向量)

【问题讨论】:

  • 请发布完整的 Traceback。
  • @miindlek 刚刚更新了我的帖子

标签: python numpy scipy mathematical-optimization


【解决方案1】:

使用least_squares。这将需要稍微修改目标以返回差异而不是平方差异:

import numpy as np
from scipy.optimize import least_squares

P = np.matrix([[0.3, 0.1, 0.2], [0.01, 0.4, 0.2], [0.0001, 0.3, 0.5]])  
Ps = np.array([10,14,5])

def objective(x):
    x = np.array([x])
    res = Ps - np.dot(x, P)
    return np.asarray(res).flatten()

def main():
    x = np.array([10, 11, 15])
    print(least_squares(objective, x))

结果:

 active_mask: array([0., 0., 0.])
        cost: 5.458917464129402e-28
         fun: array([1.59872116e-14, 2.84217094e-14, 5.32907052e-15])
        grad: array([-8.70414856e-15, -1.25943700e-14, -1.11926469e-14])
         jac: array([[-3.00000002e-01, -1.00000007e-02, -1.00003682e-04],
       [-1.00000001e-01, -3.99999999e-01, -3.00000001e-01],
       [-1.99999998e-01, -1.99999999e-01, -5.00000000e-01]])
     message: '`gtol` termination condition is satisfied.'
        nfev: 4
        njev: 4
  optimality: 1.2594369966691647e-14
      status: 1
     success: True
           x: array([ 31.95419775,  41.56815698, -19.40894189])

【讨论】:

    【解决方案2】:

    您的目标函数需要返回一个标量值,而不是一个向量。您可能希望返回平方误差的 sum,而不是平方误差的向量:

    def objective(x):
        res = ((Ps - np.dot(x, P)) ** 2).sum()
        return res 
    

    【讨论】:

    • 我更新了我的帖子,有一个功能要最小化。它返回一个向量,而不是一个标量值。 Ps - 是一个向量。
    • @Rachnog 嗯……这是个问题。您的loss function 总是 必须返回一个标量值,以反映当前参数集的整体“优点”。暂时假设目标函数返回一个向量。我发现增加x[0] 会减少objective(x)[0] 但会增加objective(x)[1]。我应该如何更新x
    • 我应该考虑一下,可能是相关文章的错误或者我不明白Ps的意义:)
    • 通常将最小二乘问题转换为标量函数的最小化是一个糟糕的建议,因为这样会丢失有关 x 结构的信息,并且可能需要更多的迭代才能收敛,或者它可以无法完全收敛
    【解决方案3】:

    如果您希望生成的向量是仅包含 0s 的向量,则可以使用 fsolve 来实现。为此,您需要稍微修改一下目标函数,以使输入和输出具有相同的形状:

    import scipy.optimize as so
    P = np.matrix([[0.3, 0.1, 0.2], [0.01, 0.4, 0.2], [0.0001, 0.3, 0.5]])  
    Ps = np.array([10,14,5])
    
    def objective(x):   
        x = np.array([x])
        res = np.square(Ps - np.dot(x, P)) 
        return np.array(res).ravel() 
    Root = so.fsolve(objective, x0=np.array([10, 11, 15]))
    objective(Root)
    #[  5.04870979e-29   1.13595970e-28   1.26217745e-29]
    

    结果:解决方案是np.array([ 31.95419775, 41.56815698, -19.40894189])

    【讨论】:

    • +1 fsolve 我应该想到了!不过,值得指出的是,fsolve 使用MINPACK hybrd.f 最小化向量的欧几里得范数,因此内部使用的实际“目标函数”将相当于我的平方根。损失函数仍然需要有一个标量输出。
    猜你喜欢
    • 2011-07-14
    • 1970-01-01
    • 2021-12-28
    • 2014-06-07
    • 1970-01-01
    • 2012-05-29
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    相关资源
    最近更新 更多