【问题标题】:Optimizing a function where one of the parameters is an array优化参数之一是数组的函数
【发布时间】:2018-05-22 21:40:46
【问题描述】:

我想通过改变其中两个参数实际上是数组的参数来优化函数。我试过了

...
# initial parameters
params0 = np.array([p1, p2, ... , p_array1, p_array2])
p_min = minimize(myfunc, params0, args)
...

pj 是标量,p_array1 和 p_array2 是长度相同的数组,但这给了我一个错误提示

ValueError: setting an array element with a sequence.

我还尝试将 p_array1 和 p_array2 作为标量传递到 myfunc 中,然后从 myfunc 中的这两个创建预定数组(例如,设置 p_array1 = p_array1*np.arange(6) 并类似地设置 p_array2),消除了错误,但是我不希望它们被预先确定——相反,我希望“最小化”以弄清楚它们应该是什么。

有什么方法可以利用 Scipy 的优化函数之一而不会出现此错误,同时仍将 p_array1 和 p_array2 保留为数组而不是标量?

编辑

对不起,这里是我的代码:

注意:这里的'myfunc'实际上是norm_residual

import pandas as pd
import numpy as np

def f(yvec, t, a, b, c, d, M, theta):
    # the system of ODEs to be solved
    x, y = yvec
    dydt = [ a*x - b*y**2 + 1, -c*x - d*x*y + np.sum(M * np.cos(theta*t)) ]
    return dydt

ni = 3 # the number of periodic forcing functions to add to the DE system
M = 0.56*np.random.rand(ni) # the initial amplitudes of forcing functions
theta = np.pi/6*np.arange(ni) # the initial coefficients of the forcing functions

# initialize the parameters
params0 = [0.75, 0.23, 1.0, 0.2, M, theta]

# grabbing the data to be used later
data = pd.read_csv('data.csv')
y_data = data['Y']

N = y_data.shape[0] #20
t = np.linspace(0, N, N) # array of t values to integrate over
yvec0 = [0.3, 0.34] # initial conditions for x and y respectively

def norm_residual(params, *args):
    """
    Computes the L^2 norm of the residual of y and the data (y as defined above).
    Input:    params = array of parameters (scalars or arrays) for the DE system
              args = other arguments to pass into the function f or to use
                   to compute the residual.
    Output: err = L^2 error of the solution vector (scalar).
    """
    data, yvec0, t = args
    a, b, c, d, M, theta = params
    sol = odeint(f, yvec0, t, args=(a, b, c, d, M, theta))
    x = sol[:, 0]; y = sol[:, 1]
    res = data - y
    err = np.linalg.norm(res, 2)
    return err

from scipy.optimize import minimize

p_min = minimize(norm_residual, params0, args=(y_data, yvec0, t))
print(p_min)

还有回溯

Traceback (most recent call last):
  File "model_ex_1.py", line 62, in <module>
    p_min = minimize(norm_residual, params0, args=(y_anom, yvec0, t))
  File "/usr/lib/python2.7/dist-packages/scipy/optimize/_minimize.py", line 354, in minimize
    x0 = np.asarray(x0)
  File "/usr/lib/python2.7/dist-packages/numpy/core/numeric.py", line 482, in asarray
    return array(a, dtype, copy=False, order=order)
ValueError: setting an array element with a sequence.

【问题讨论】:

  • 你能发布myfunc的完整回溯和来源吗?
  • 无论你做什么,你都必须使用扁平化视图来最小化 API!如果有参数:p1, p2, p3, p_array1, p_array2 其中len(p_array1) = N 和len(p_array2) = M,您将需要提供大小为3 + N + M 的x0,您可以在您的函数(可能是第一行)中解压缩这些参数,例如p1, p2, p3 = x[:3] , p_array1 = x[3:3+N]p_array2 = x[3+3+N:] 并在这些混合类型上做任何你想做的事情。 params0 可能由 np.hstack((p1, p2, p3, p_array1, p_array2)) 或以某种类似方式(在某些假设下)创建。
  • @YakymPirozhenko 我已经编辑了我的帖子以包含更多代码和回溯。请参阅上面的注释。
  • 为什么我的帖子被否决了?如我的帖子所示,我已经投入了一些研究工作,如我的试验和错误所示。如果是因为清晰或有用,我还包括了我的 ODE 系统的函数定义。

标签: python optimization scipy


【解决方案1】:

如果其他元素是标量,则不能将列表放入 numpy 数组中。

>>> import numpy as np
>>> foo_array = np.array([1,2,3,[5,6,7]])
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    foo_array = np.array([1,2,3,[5,6,7]])
ValueError: setting an array element with a sequence.

【讨论】:

    【解决方案2】:

    如果你发帖myfunc会很有帮助 但你可以这样做 -

    def foo():
        return [p0,p1,p2..pn]
    
    params0 = numpy.array([foo(), p_array1, p_array2])
    p_min = minimize(myfunc, params0, args) 
    

    或来自Multiple variables in SciPy's optimize.minimize

    import scipy.optimize as optimize
    
    def f(params):
        # print(params)  # <-- you'll see that params is a NumPy array
        a, b, c = params # <-- for readability you may wish to assign names to the component variables
        return a**2 + b**2 + c**2
    
    initial_guess = [1, 1, 1]
    result = optimize.minimize(f, initial_guess)
    if result.success:
        fitted_params = result.x
        print(fitted_params)
    else:
        raise ValueError(result.message)
    

    【讨论】:

    • 我已经编辑了我的帖子并包含更多代码,如果有帮助的话。我会努力实现这个想法。
    【解决方案3】:

    我想通了!我发现可行的解决方案是改变

    params0 = [0.75, 0.23, 1.0, 0.2, M, theta]
    

    在第 6 行到

    params0 = np.array([ 0.75, 0.23, 1.0, 0.2, *M, *theta], dtype=np.float64)
    

    在我的 ODE 系统的函数定义中,而不是有

    def f(yvec, t, a, b, c, d, M, theta):
        x, y = yvec
        dydt = [ a*x - b*y**2 + 1, -c*x - d*x*y + np.sum(M * np.cos(theta*t)) ]
        return dydt
    

    我现在有

    def f(yvec, t, myparams):
        x, y = yvec
        a, b, c, d = myparams[:4]
        ni = (myparams[4:].shape[0])//2 # halved b/c M and theta are of the same shape
        M = myparams[4:ni+4]
        theta = myparams[ni+4:]
        dydt = [ a*x - b*y**2 + 1, -c*x - d*x*y + np.sum(M * np.cos(theta*t)) ]
        return dydt
    

    注意:我必须为“params0”添加“dtype=np.float64”,因为我遇到了错误

    AttributeError: 'numpy.float64' object has no attribute 'cos'
    

    当我没有它时,'cos' 似乎不知道如何处理'ndarray' 对象。解决方法可以在here找到。

    感谢大家的建议!

    【讨论】:

      猜你喜欢
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      • 2020-01-23
      • 1970-01-01
      • 2013-12-27
      • 1970-01-01
      • 2012-06-04
      相关资源
      最近更新 更多