Я максимизирую LogLikelihood модели ARMA, используя пакет scipy.optimize.minimize и используя метод BFGS. Однако я получаю следующую ошибку:
The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Функция, которую я оптимизирую, возвращает правильный вывод, то есть логарифмическую вероятность указанной модели ARMA, поэтому я пытаюсь посмотреть на исходный код пакета минимизации, однако это довольно сложно, и я не могу понять, что проблема в. Я понимаю, что это не простой вопрос, однако я надеюсь, что кто-то, имеющий опыт использования пакета минимизации, может дать мне несколько советов о том, что может быть причиной ошибки.
Данная трассировка выглядит следующим образом:
ValueError Traceback (most recent call last)
/......../.py in fit_ARMA(data, p, q)
150 optim_args=(data, p, q)
151
--> 152 fitted_params = minimize(minus_ll_ARMA, x0=init_params, args=optim_args, method='BFGS')
153
154 return fitted_params.x
/anaconda3/lib/python3.6/site-packages/scipy/optimize/_minimize.py in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
595 return _minimize_cg(fun, x0, args, jac, callback, **options)
596 elif meth == 'bfgs':
--> 597 return _minimize_bfgs(fun, x0, args, jac, callback, **options)
598 elif meth == 'newton-cg':
599 return _minimize_newtoncg(fun, x0, args, jac, hess, hessp, callback,
/anaconda3/lib/python3.6/site-packages/scipy/optimize/optimize.py in _minimize_bfgs(fun, x0, args, jac, callback, gtol, norm, eps, maxiter, disp, return_all, **unknown_options)
981 alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 = \
982 _line_search_wolfe12(f, myfprime, xk, pk, gfk,
--> 983 old_fval, old_old_fval, amin=1e-100, amax=1e100)
984 except _LineSearchError:
985 # Line search failed to find a better solution.
/anaconda3/lib/python3.6/site-packages/scipy/optimize/optimize.py in _line_search_wolfe12(f, fprime, xk, pk, gfk, old_fval, old_old_fval, **kwargs)
801 ret = line_search_wolfe1(f, fprime, xk, pk, gfk,
802 old_fval, old_old_fval,
--> 803 **kwargs)
804
805 if ret[0] is not None and extra_condition is not None:
/anaconda3/lib/python3.6/site-packages/scipy/optimize/linesearch.py in line_search_wolfe1(f, fprime, xk, pk, gfk, old_fval, old_old_fval, args, c1, c2, amax, amin, xtol)
99 stp, fval, old_fval = scalar_search_wolfe1(
100 phi, derphi, old_fval, old_old_fval, derphi0,
--> 101 c1=c1, c2=c2, amax=amax, amin=amin, xtol=xtol)
102
103 return stp, fc[0], gc[0], fval, old_fval, gval[0]
/anaconda3/lib/python3.6/site-packages/scipy/optimize/linesearch.py in scalar_search_wolfe1(phi, derphi, phi0, old_phi0, derphi0, c1, c2, amax, amin, xtol)
153
154 if old_phi0 is not None and derphi0 != 0:
--> 155 alpha1 = min(1.0, 1.01*2*(phi0 - old_phi0)/derphi0)
156 if alpha1 < 0:
157 alpha1 = 1.0
/anaconda3/lib/python3.6/site-packages/pandas/core/generic.py in __nonzero__(self)
1574 raise ValueError("The truth value of a {0} is ambiguous. "
1575 "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
-> 1576 .format(self.__class__.__name__))
1577
1578 __bool__ = __nonzero__
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Ниже приведены две используемые функции:
def ll_ARMA(params, data, p, q):
'''Returns the log-likelihood of the ARMA model.
Data index must be increasing (oldest observations on top)
p= # coeff. AR
q= # coeff MA'''
n = data.shape[0]
if p>0:
lagged_data = data.shift(1).copy()
for i in range(1,p):
lagged_data = pd.concat([lagged_data, data.shift(i+1)], axis=1)
else:
lagged_data = pd.DataFrame(index = data.index, columns=[i+1 for i in range(p)])
errors_index = pd.Index([i for i in range(q)]).append(data.index)
errors = pd.DataFrame(np.zeros(shape=(n+q,1)),index=errors_index)
for i in range(q, n+q):
a = data.iloc[i-q,:] - params[0] - np.sum(np.dot(lagged_data, params[1:p+1])) - \
np.dot(params[p+1:], np.asarray([errors.iloc[i-j,:] for j in range(1, q+1)]))
errors.iloc[i,:] = a.item()
errors = errors[q:] # gets rid of initial q values set at 0
var = np.var(errors)
log_likelihood = np.log(2*np.pi*var)*(-1/2) + (-1/2)*(errors**2)/var
return np.sum(log_likelihood)
def fit_ARMA(data, p, q):
'''Returns the fitted parameters of an ARMA model (including the constant).
Order is -constant -p AR coeff -q MA coeff
Data must be a 1-column DF.
p is the parameter of the AR, q of the MA'''
init_params = np.random.random(p+q+1)
def minus_ll_ARMA(params, data, p, q):
return -1*ll_ARMA(params, data, p, q)
optim_args=(data, p, q)
fitted_params = minimize(minus_ll_ARMA, x0=init_params, args=optim_args, method='BFGS')
return fitted_params.x
И это работоспособный пример, который выдает ошибку:
import pandas as pd # version 0.23.4
import numpy as np # version 1.15.4
from scipy.optimize import minimize # version 1.1.0
data = pd.DataFrame(np.random.random(500)*0.4-0.2, index = [i for i in range(1,501)]) # randomly generates returns in a sensible range
parameters = fit_ARMA(data, 2, 3) # this returns the error
P.S. Я уже изучил следующий вопрос: scipy.optimize.minimize Якобианская функция вызывает 'Ошибка значения: Истинное значение массива с более чем одним элементом неоднозначно' , однако я не включаю градиент, поэтому ошибка имеет другую природу.