1

Based on this post I am trying to use brute to do a grid serach on a ARIMA model but I cannot make it run. I am doign this proof of principle, but what am I doing wrong with the arguments?

y = pd.DataFrame([0,1,4,9,16]) + 3
def objfunc(coeffs, endog):
    exp = coeffs[0]
    const = coeffs[1]
    print(exp, const, endog)
    out = 0
    for i in range(4):
        out += i**exp + const
    return out

from scipy.optimize import brute
grid = (slice(0, 2, 1), slice(3, 4, 1))
brute(objfunc, ranges=grid, args=y)

(0, 3, 0)
(0, 3, 0)
(1, 3, 0)
...
TypeError: objfunc() takes exactly 2 arguments (1 given)

Once I solve this my aim is actually to optimize this function on order and seasonal_order being tuples like this ( _ , _ , _ ) and this ( _ , _ , _ ,12), respectively.

def objfunc(coeffs, endog):
    order = coeffs[0]
    seasonal = coeffs[1]
    fit = sm.tsa.statespace.SARIMAX(endog, trend='n', order=order, seasonal_order=seasonal).fit()
    return fit.aic()

EDIT: this code works (thanks to @sasha), variable names are more clear, and makes more sense (I minimize the function on the error).

import pandas as pd    
y = np.array([0,1,4,9,16]) + 3 #polynomial x^2+3 with x=0:4
def objfunc(coeffs, *args):
    arr = args[0]                       # access first element of tuple: y
    exp = coeffs[0]                       #     assuming y should become endog
    const = coeffs[1]
    pol = [i**exp + const for i in range(len(y))]
    print coeffs
    return abs(sum(pol) - sum(arr))

from scipy.optimize import brute
grid = (slice(1, 3, 1), slice(2, 5, 1))
resbrute = brute(objfunc, ranges=grid, args=(y,), full_output=True, finish=None)
print("Best coeffs: {}".format(resbrute[0]))
print("Score with best coeffs: {}".format(resbrute[1]))
print("Grid: {}".format(resbrute[2].tolist()))
print("Scores for grid: {}".format(resbrute[3].tolist()))
aless80
  • 3,122
  • 3
  • 34
  • 53

1 Answers1

2

The code looks a bit strange with all those variable-names. endog, y; y becomes endog?

But the following is probably the approach, which follows exactly the documentation

args : tuple, optional

Any additional fixed parameters needed to completely specify the function.

Code:

import pandas as pd

y = pd.DataFrame([0,1,4,9,16]) + 3
def objfunc(coeffs, *args):
    endog = args[0]                       # access first element of tuple: y
    exp = coeffs[0]                       #     assuming y should become endog
    const = coeffs[1]
    print(exp, const, endog)
    out = 0
    for i in range(4):
        out += i**exp + const
    return out

from scipy.optimize import brute
grid = (slice(0, 2, 1), slice(3, 4, 1))
brute(objfunc, ranges=grid, args=(y,))    # in general a tuple; first pos: y
Community
  • 1
  • 1
sascha
  • 32,238
  • 6
  • 68
  • 110
  • 1
    You are right with variable names. I edited my question and included your answer. I could make my optimization on SARIMAX work and i will probably post it. Thank you – aless80 Dec 10 '17 at 15:29