函数返回向量,如何通过NumPy进行最小化

2 投票
4 回答
4747 浏览
提问于 2025-04-18 16:32

我正在尝试最小化一个函数,这个函数会返回一组值,结果出现了一个错误:

设置数组元素时出现了序列问题

代码如下:

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 ]]

感谢任何建议

更新(完整的错误追踪信息)

    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.

更新2:这个函数应该被最小化(Ps是一个向量)

在这里输入图片描述

4 个回答

0

你的问题

在这些P、Ps的值下,x函数返回的结果是 [[ 47.45143225 16.81 44.89 ]]

你的回答

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

你到底需要什么结果呢?你的ValueError提示说明变量的形状有问题,你可以参考自己的代码,像这样:

from scipy.optimize import minimize
import numpy as np

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):
    res = np.square(Ps - np.dot(x, P)).sum()    # <<<<< sum
    return res

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

if __name__ == '__main__':
    main()

但最终的结果还是像上面提供的fsolve_Solution,而不是你在讨论中提到的那样。

final_simplex: (array([[ 31.95415651,  41.5681525 , -19.40893553],
       [ 31.95421376,  41.56815815, -19.40892458],
       [ 31.95417772,  41.56820834, -19.40895555],
       [ 31.9541516 ,  41.56814833, -19.40890433]]), array([2.05803682e-10, 2.22144587e-10, 2.39097188e-10, 2.65258467e-10]))
           fun: 2.0580368213652934e-10
       message: 'Optimization terminated successfully.'
          nfev: 167
           nit: 92
        status: 0
       success: True
             x: array([ 31.95415651,  41.5681525 , -19.40893553])
0

使用 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

你的目标函数需要返回一个单一的数值,而不是一个向量。你可能想要返回的是平方误差的总和,而不是平方误差的向量:

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

如果你想要得到的结果是一个只包含 0 的向量,你可以使用 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])

撰写回答