Reputation: 11
I've been trying to optimize three coefficients. But I cannot solve the error I faced. The following is the codes. 'y' is the forecasting function whcih takes a list of time series data and a coefficient list and then returns a list of forecasts after calculation. x is the historical data. and coeffList is a list which has 3 coefficients as a value.
'mape' function calculates the difference between actual and forecasted data. In the optimization, I'm trying to minimize the output from the 'mape' function. As constraints, all three coefficients are greater than 0 and less than 1.
from __future__ import division
import numpy as np
from scipy.optimize import minimize
#coeffList[0] = alpha
#coeffList[1] = beta
#coeffList[2] =gamma
def mape(x, coeffList):
diff = abs(y(x,coeffList)-x)
print("np.mean(diff/x) : ", np.mean(diff/x))
return np.mean(diff/x)
#Holt Winters-Multiplicative
def y(x, coeffList , debug=True):
c =4
#Compute initial b and intercept using the first two complete c periods.
xlen =len(x)
print("xlen : ", xlen)
#if xlen % c !=0:
# return None
fc =float(c)
xbar2 =sum([x[i] for i in range(c, 2 * c)])/ fc
print("xbar2 : ",xbar2)
xbar1 =sum([x[i] for i in range(c)]) / fc
print("xbar1 : ", xbar1)
b0 =(xbar2 - xbar1) / fc
if debug: print ("b0 = ", b0)
#Compute for the level estimate a0 using b0 above.
tbar =sum(i for i in range(1, c+1)) / fc
print("tbar : ",tbar)
a0 =xbar1 - b0 * tbar
if debug: print ("a0 = ", a0)
#Compute for initial indices - seasonality
I =[x[i] / (a0 + (i+1) * b0) for i in range(0, xlen)]
if debug: print ("Initial indices = ", I)
S=[0] * (xlen+ c)
for i in range(c):
S[i] =(I[i] + I[i+c]) / 2.0
print ("S[",i,"]=", S[i])
#Normalize so S[i] for i in [0, c) will add to c.
tS =c / sum([S[i] for i in range(c)])
print("tS : ", tS)
for i in range(c):
S[i] *=tS
if debug: print ("Normalized S[",i,"]=", S[i])
# Holt - winters proper ...
if debug: print( "Use Holt Winters formulae")
At =a0
Bt =b0
#y =[0] * (xlen)
y = np.empty(len(x),float)
for i in range(xlen):
Atm1 =At # a[0] = a0
Btm1 =Bt # b[0] = b0
At =coeffList[0] * x[i] / S[i] + (1.0-coeffList[0]) * (Atm1 + Btm1)
Bt =coeffList[1] * (At - Atm1) + (1- coeffList[1]) * Btm1
S[i+c] =coeffList[2] * x[i] / At + (1.0 - coeffList[2]) * S[i]
y[i]=(a0 + b0 * (i+1)) * S[i]
return y
# the time-series data.
coeff = [0.2, 0.3, 0.4]
x =[146, 96, 59, 133, 192, 127, 79, 186, 272, 155, 98, 219]
test = y(x,coeff)
print("x : ", x)
print("y : ",test)
#optimization
result = minimize(mape, coeff, (x,), bounds =[(0,1),(0,1), (0,1)], method='SLSQP')
opt = result.x
print("opt : ", result.x)
And this is the error message I have :
Traceback (most recent call last):
File "C:\Users\SEC\Desktop\HDWeathProgram\testing_Optimization_HWM.py", line 135, in <module>
result = minimize(mape, coeff, (x,), bounds =[(0,1),(0,1), (0,1)], method='SLSQP')
File "C:\Python27\lib\site-packages\scipy\optimize\_minimize.py", line 364, in minimize
constraints, **options)
File "C:\Python27\lib\site-packages\scipy\optimize\slsqp.py", line 354, in _minimize_slsqp
fx = func(x)
File "C:\Python27\lib\site-packages\scipy\optimize\optimize.py", line 261, in function_wrapper
return function(x, *args)
File "C:\Users\SEC\Desktop\HDWeathProgram\testing_Optimization_HWM.py", line 12, in mape
diff = abs(y(x,coeffList)-x)
File "C:\Users\SEC\Desktop\HDWeathProgram\testing_Optimization_HWM.py", line 30, in y
xbar2 =sum([x[i] for i in range(c, 2 * c)])/ fc
IndexError: index 4 is out of bounds for axis 0 with size 3
What kind of problems do I have? I will really appreciate any kind of your comments
Upvotes: 1
Views: 1375
Reputation: 17711
The call that generates the IndexError: index 4 is out of bounds for axis 0 with size 3
is the minimize call. This is because your objective function you are minimizing tries minimizing the first parameter.
You appear by your bounds to want to minimize the coeff
(a three dimensional thing), but currently you are trying to minimize the first parameter of mape
which is x
. Thus, your function has its input parameters in the wrong order. You can fix this quickly with say (or by redefining mape
(change first line to def mape(x, coeffList):
).
def mape_reversed(coeffList, x):
return mape(x, coeffList)
result = minimize(mape_reversed, coeff, (x,), bounds =[(0,1),(0,1), (0,1)], method='SLSQP')
Upvotes: 1