Python: scipy.optimize.minimize терпит неудачу с «ValueError: установка элемента массива с последовательностью».при вызове функции с аргументами x и y - PullRequest
0 голосов
/ 29 сентября 2018

Как указано в заголовке, scipy.optimize.minimize терпит неудачу с «ValueError: установка элемента массива с последовательностью».при вызове minim.

Я применяю scipy.optimize.minimize к функции, которая использует переменные coef (коэффициенты, которые я оптимизирую) и xData и yData (переменные данных).

Я приведу пример кода ниже.Я знаю, что благодаря поиску способов использования минимума ошибка возникает из-за минимизируемой функции, возвращающей массив, когда он должен возвращать скаляр.Я не уверен, , почему возвращает массив, хотя.

Важно, что scipy.optimize.least_squares работает и, похоже, использует тот же синтаксис, что и scipy.optimize.minimize.scipy.optimize.fmin также не работает, и он также включен - он такой же, как свернуть с помощью метода Nelder-Mead, который я вызываю.

Вот несколько обобщенных примеров кода, в котором ошибка включенаPython 3:

import numpy as np
from scipy.optimize import least_squares
from scipy.optimize import minimize
from scipy.optimize import fmin
import matplotlib.pyplot as plt

xData = np.linspace(50,94,334);
yData = (xData-75)**2 + (np.random.random((334,))-.5)*600;

fun = lambda coef, x : coef[0] + coef[1]*x + coef[2]*x**2 ; #create a "lambda" function whatever that is that has a tuple for the polynomial coefficients in it
#function is y = coef0 + coef1*x + coef2*x^2 where y is lambda

funError = lambda coef, x, y: fun(coef,x) - y; #create a "lambda" function for the error between the real data y and the fit data y
#function is yError = y(coef,x) - yReal where yError is the lambda now
#expanded fully: yError = coef0 + coef1*x + coef2*x^2 - yReal

coef_init = (5,10,15); #initial coefficient guess
#coef0 is const (order 0)
#coef1 is order 1 coef
#coef2 is order 2 coef

coef = least_squares(funError,coef_init, args=(xData,yData) ); #calculate the polynomial coefficients to fit the data
yFit_lq = fun(coef.x,xData); #calc the guessed values 
plt.figure();
plt.scatter( xData , yData , 20 , "r" );
plt.scatter( xData , yFit_lq , 20 );
plt.title("Least Squares");
plt.show();

coef = minimize(funError,coef_init, args=(xData,yData),method="Nelder-Mead" ); #calculate the polynomial coefficients to fit the data
yFit_min = fun(coef.x,xData); #calc the guessed values 
plt.figure();
plt.scatter( xData , yData , 20 , "r" );
plt.scatter( xData , yFit_min , 20 );
plt.title("Minimize with Nelder-Mead");
plt.show();

coef = fmin(funError,coef_init, args=(xData,yData) ); #calculate the polynomial coefficients to fit the data
yFit_fmin = fun(coef.x,xData); #calc the guessed values 
plt.figure();
plt.scatter( xData , yData , 20 , "r" );
plt.scatter( xData , yFit_fmin , 20 );
plt.title("fmin, equiv to min. w/ neldy");
plt.show();

Я вызываю наименьшие квадраты, минимизирую и fmin таким же образом, а их страницы просто запрашивают args = ().Я не уверен, что происходит неправильно при вызове метода minim и fmin, что «ValueError: установка элемента массива с последовательностью».ошибка возникает в то время как наименьшее количество квадратов полностью устраивает форматирование.

Я также предпочел бы избегать лишних функций defs - простая и понятная лямбда-функция должна быть в состоянии справиться с этим простым случаем.

1 Ответ

0 голосов
/ 29 сентября 2018

least_squares и minimize предъявляют различные требования к целевой функции.

least_squares ожидает, что ваша функция вернет вектор.Строка документации описывает этот вектор как «вектор невязок».least_squares берет этот вектор и суммирует квадраты элементов, чтобы сформировать фактическую целевую функцию, которая минимизируется.

minimize ожидает, что ваша целевая функция вернется скаляр .Он пытается найти векторное входное значение, которое минимизирует скалярный вывод вашей функции.

Вы можете решить задачу оптимизации наименьших квадратов с помощью minimize, изменив существующую функцию, чтобы она вычисляла и возвращала сумму квадратовостатки:

def funError(coef, x, y):
    residuals = fun(coef,x) - y
    objective = (residuals**2).sum()
    return objective

Но тогда эта функция не настроена для использования с least_squares.Таким образом, вместо этого вы можете использовать две функции:

def funError(coef, x, y):
    residuals = fun(coef,x) - y
    return residuals

def funErrorSSR(coef, x, y):
    residuals = funError(coef, x, y)
    objective = (residuals**2).sum()
    return objective

Использовать funError с least_squares и funErrorSSR с minimize (или fmin).

...