In [1]:
# remove the notebook root logger.\n",
import logging
logger = logging.getLogger()
logger.handlers = []

%matplotlib inline

In [2]:
import pandas as pd


csvfile_link = "https://raw.githubusercontent.com/antoinecarme/TimeSeriesData/master/ozone-la.csv"
ozone_dataframe = pd.read_csv(csvfile_link);
import datetime
ozone_dataframe['Month'] = ozone_dataframe['Month'].apply(lambda x : datetime.datetime.strptime(x, "%Y-%m"))
ozone_dataframe.head()


Out[2]:
Month Ozone
0 1955-01-01 2.7
1 1955-02-01 2.0
2 1955-03-01 3.6
3 1955-04-01 5.0
4 1955-05-01 6.5

In [3]:
def create_model(iActivateCrossVal , iFolds):
    import pyaf.ForecastEngine as autof
    lEngine = autof.cForecastEngine()
    if(iActivateCrossVal):
        lEngine.mOptions.mCrossValidationOptions.mMethod = "TSCV";
        lEngine.mOptions.mCrossValidationOptions.mNbFolds = iFolds
    lEngine.train(ozone_dataframe[:-12] , 'Month' , 'Ozone', 12);
    lEngine.getModelInfo();
    return lEngine

In [4]:
model_no_cross_valid = create_model(False , None)
model_with_cross_valid_5 = create_model(True , 5)
model_with_cross_valid_10 = create_model(True , 10)


INFO:pyaf.std:START_TRAINING 'Ozone'
INFO:pyaf.std:END_TRAINING_TIME_IN_SECONDS 'Ozone' 2.7717881202697754
INFO:pyaf.std:TIME_DETAIL TimeVariable='Month' TimeMin=1955-01-01T00:00:00.000000 TimeMax=1967-09-01T00:00:00.000000 TimeDelta=<DateOffset: months=1> Horizon=12
INFO:pyaf.std:SIGNAL_DETAIL_ORIG SignalVariable='Ozone' Length=204  Min=1.2 Max=8.7  Mean=3.8357843137254903 StdDev=1.4915592159401185
INFO:pyaf.std:SIGNAL_DETAIL_TRANSFORMED TransformedSignalVariable='_Ozone' Min=1.2 Max=8.7  Mean=3.8357843137254903 StdDev=1.4915592159401185
INFO:pyaf.std:BEST_TRANSOFORMATION_TYPE '_'
INFO:pyaf.std:BEST_DECOMPOSITION  '_Ozone_LinearTrend_residue_zeroCycle_residue_AR(51)' [LinearTrend + NoCycle + AR]
INFO:pyaf.std:TREND_DETAIL '_Ozone_LinearTrend' [LinearTrend]
INFO:pyaf.std:CYCLE_DETAIL '_Ozone_LinearTrend_residue_zeroCycle' [NoCycle]
INFO:pyaf.std:AUTOREG_DETAIL '_Ozone_LinearTrend_residue_zeroCycle_residue_AR(51)' [AR]
INFO:pyaf.std:MODEL_MAPE MAPE_Fit=0.1641 MAPE_Forecast=0.1595 MAPE_Test=0.174
INFO:pyaf.std:MODEL_SMAPE SMAPE_Fit=0.1547 SMAPE_Forecast=0.178 SMAPE_Test=0.182
INFO:pyaf.std:MODEL_MASE MASE_Fit=0.6981 MASE_Forecast=0.6782 MASE_Test=0.9094
INFO:pyaf.std:MODEL_L1 L1_Fit=0.613597862427259 L1_Forecast=0.5265316758013029 L1_Test=0.42992050508902313
INFO:pyaf.std:MODEL_L2 L2_Fit=0.809570003175602 L2_Forecast=0.731568864950715 L2_Test=0.5519432695595543
INFO:pyaf.std:MODEL_COMPLEXITY 54
INFO:pyaf.std:SIGNAL_TRANSFORMATION_DETAIL_START
INFO:pyaf.std:SIGNAL_TRANSFORMATION_MODEL_VALUES NoTransf None
INFO:pyaf.std:SIGNAL_TRANSFORMATION_DETAIL_END
INFO:pyaf.std:TREND_DETAIL_START
INFO:pyaf.std:LINEAR_RIDGE_TREND LinearTrend (5.022578136250887, array([-1.82712926]))
INFO:pyaf.std:TREND_DETAIL_END
INFO:pyaf.std:CYCLE_MODEL_DETAIL_START
INFO:pyaf.std:ZERO_CYCLE_MODEL_VALUES _Ozone_LinearTrend_residue_zeroCycle 0.0 {}
INFO:pyaf.std:CYCLE_MODEL_DETAIL_END
INFO:pyaf.std:AR_MODEL_DETAIL_START
INFO:pyaf.std:AR_MODEL_COEFF 1 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag1 0.4349634413603371
INFO:pyaf.std:AR_MODEL_COEFF 2 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag10 0.19036685617533317
INFO:pyaf.std:AR_MODEL_COEFF 3 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag7 -0.16906339635225442
INFO:pyaf.std:AR_MODEL_COEFF 4 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag30 0.16128205795389375
INFO:pyaf.std:AR_MODEL_COEFF 5 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag12 0.14093045574208746
INFO:pyaf.std:AR_MODEL_COEFF 6 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag32 -0.13104711303046346
INFO:pyaf.std:AR_MODEL_COEFF 7 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag48 0.12661310040481832
INFO:pyaf.std:AR_MODEL_COEFF 8 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag36 0.12091470037102245
INFO:pyaf.std:AR_MODEL_COEFF 9 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag22 0.11845464489045833
INFO:pyaf.std:AR_MODEL_COEFF 10 _Ozone_LinearTrend_residue_zeroCycle_residue_Lag39 -0.11612291477947745
INFO:pyaf.std:AR_MODEL_DETAIL_END
INFO:pyaf.std:START_TRAINING 'Ozone'
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SIGNAL_SPLIT 'Ozone' (0.4, 0.2, 0.0)
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SPLIT_TIME_IN_SECONDS 'Ozone' (0.4, 0.2, 0.0) 1.3878464698791504
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SIGNAL_SPLIT 'Ozone' (0.6000000000000001, 0.2, 0.0)
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SPLIT_TIME_IN_SECONDS 'Ozone' (0.6000000000000001, 0.2, 0.0) 1.9790098667144775
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SIGNAL_SPLIT 'Ozone' (0.8, 0.2, 0.0)
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SPLIT_TIME_IN_SECONDS 'Ozone' (0.8, 0.2, 0.0) 2.092709541320801
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_TIME_IN_SECONDS _Ozone 5.4828431606292725
INFO:pyaf.std:END_TRAINING_TIME_IN_SECONDS 'Ozone' 6.116368055343628
INFO:pyaf.std:TIME_DETAIL TimeVariable='Month' TimeMin=1955-01-01T00:00:00.000000 TimeMax=1968-07-01T00:00:00.000000 TimeDelta=<DateOffset: months=1> Horizon=12
INFO:pyaf.std:SIGNAL_DETAIL_ORIG SignalVariable='Ozone' Length=204  Min=1.2 Max=8.7  Mean=3.8357843137254903 StdDev=1.4915592159401185
INFO:pyaf.std:SIGNAL_DETAIL_TRANSFORMED TransformedSignalVariable='_Ozone' Min=1.2 Max=8.7  Mean=3.8357843137254903 StdDev=1.4915592159401185
INFO:pyaf.std:BEST_TRANSOFORMATION_TYPE '_'
INFO:pyaf.std:BEST_DECOMPOSITION  '_Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_AR(51)' [LinearTrend + Cycle + AR]
INFO:pyaf.std:TREND_DETAIL '_Ozone_LinearTrend' [LinearTrend]
INFO:pyaf.std:CYCLE_DETAIL '_Ozone_LinearTrend_residue_bestCycle_byMAPE' [Cycle]
INFO:pyaf.std:AUTOREG_DETAIL '_Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_AR(51)' [AR]
INFO:pyaf.std:MODEL_MAPE MAPE_Fit=0.1651 MAPE_Forecast=0.1642 MAPE_Test=None
INFO:pyaf.std:MODEL_SMAPE SMAPE_Fit=0.1559 SMAPE_Forecast=0.1717 SMAPE_Test=None
INFO:pyaf.std:MODEL_MASE MASE_Fit=0.6952 MASE_Forecast=0.7151 MASE_Test=None
INFO:pyaf.std:MODEL_L1 L1_Fit=0.6093994800418591 L1_Forecast=0.5024165588324665 L1_Test=None
INFO:pyaf.std:MODEL_L2 L2_Fit=0.8088276464472037 L2_Forecast=0.6245207507824827 L2_Test=None
INFO:pyaf.std:MODEL_COMPLEXITY 64
INFO:pyaf.std:SIGNAL_TRANSFORMATION_DETAIL_START
INFO:pyaf.std:SIGNAL_TRANSFORMATION_MODEL_VALUES NoTransf None
INFO:pyaf.std:SIGNAL_TRANSFORMATION_DETAIL_END
INFO:pyaf.std:TREND_DETAIL_START
INFO:pyaf.std:LINEAR_RIDGE_TREND LinearTrend (4.9984819530936715, array([-1.88052118]))
INFO:pyaf.std:TREND_DETAIL_END
INFO:pyaf.std:CYCLE_MODEL_DETAIL_START
INFO:pyaf.std:BEST_CYCLE_LENGTH_VALUES _Ozone_LinearTrend_residue_bestCycle_byMAPE 5 0.010893766306880437 {0: 0.010893766306880437, 1: -0.026303134362841263, 2: -0.18531605326353429, 3: 0.0712668966515344, 4: 0.08291915072465006}
INFO:pyaf.std:CYCLE_MODEL_DETAIL_END
INFO:pyaf.std:AR_MODEL_DETAIL_START
INFO:pyaf.std:AR_MODEL_COEFF 1 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag1 0.39310178355150555
INFO:pyaf.std:AR_MODEL_COEFF 2 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag10 0.2077109597517221
INFO:pyaf.std:AR_MODEL_COEFF 3 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag12 0.18693273099236524
INFO:pyaf.std:AR_MODEL_COEFF 4 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag30 0.16831312130329268
INFO:pyaf.std:AR_MODEL_COEFF 5 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag7 -0.1489731891335221
INFO:pyaf.std:AR_MODEL_COEFF 6 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag36 0.12712172738176897
INFO:pyaf.std:AR_MODEL_COEFF 7 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag39 -0.11272707273702265
INFO:pyaf.std:AR_MODEL_COEFF 8 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag51 -0.11188375568072448
INFO:pyaf.std:AR_MODEL_COEFF 9 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag29 -0.11082841509257715
INFO:pyaf.std:AR_MODEL_COEFF 10 _Ozone_LinearTrend_residue_bestCycle_byMAPE_residue_Lag16 -0.11047836936498033
INFO:pyaf.std:AR_MODEL_DETAIL_END
INFO:pyaf.std:START_TRAINING 'Ozone'
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SIGNAL_SPLIT 'Ozone' (0.5, 0.1, 0.0)
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SPLIT_TIME_IN_SECONDS 'Ozone' (0.5, 0.1, 0.0) 1.5637619495391846
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SIGNAL_SPLIT 'Ozone' (0.6000000000000001, 0.1, 0.0)
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SPLIT_TIME_IN_SECONDS 'Ozone' (0.6000000000000001, 0.1, 0.0) 2.175692081451416
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SIGNAL_SPLIT 'Ozone' (0.7000000000000001, 0.1, 0.0)
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SPLIT_TIME_IN_SECONDS 'Ozone' (0.7000000000000001, 0.1, 0.0) 2.0776889324188232
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SIGNAL_SPLIT 'Ozone' (0.8, 0.1, 0.0)
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SPLIT_TIME_IN_SECONDS 'Ozone' (0.8, 0.1, 0.0) 2.108132839202881
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SIGNAL_SPLIT 'Ozone' (0.9, 0.1, 0.0)
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_SPLIT_TIME_IN_SECONDS 'Ozone' (0.9, 0.1, 0.0) 2.1236400604248047
INFO:pyaf.std:CROSS_VALIDATION_TRAINING_TIME_IN_SECONDS _Ozone 10.079196453094482
INFO:pyaf.std:END_TRAINING_TIME_IN_SECONDS 'Ozone' 10.740383863449097
INFO:pyaf.std:TIME_DETAIL TimeVariable='Month' TimeMin=1955-01-01T00:00:00.000000 TimeMax=1968-07-01T00:00:00.000000 TimeDelta=<DateOffset: months=1> Horizon=12
INFO:pyaf.std:SIGNAL_DETAIL_ORIG SignalVariable='Ozone' Length=204  Min=1.2 Max=8.7  Mean=3.8357843137254903 StdDev=1.4915592159401185
INFO:pyaf.std:SIGNAL_DETAIL_TRANSFORMED TransformedSignalVariable='_Ozone' Min=1.2 Max=8.7  Mean=3.8357843137254903 StdDev=1.4915592159401185
INFO:pyaf.std:BEST_TRANSOFORMATION_TYPE '_'
INFO:pyaf.std:BEST_DECOMPOSITION  '_Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_AR(51)' [PolyTrend + Cycle_None + AR]
INFO:pyaf.std:TREND_DETAIL '_Ozone_PolyTrend' [PolyTrend]
INFO:pyaf.std:CYCLE_DETAIL '_Ozone_PolyTrend_residue_bestCycle_byMAPE' [Cycle_None]
INFO:pyaf.std:AUTOREG_DETAIL '_Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_AR(51)' [AR]
INFO:pyaf.std:MODEL_MAPE MAPE_Fit=0.1581 MAPE_Forecast=0.1382 MAPE_Test=None
INFO:pyaf.std:MODEL_SMAPE SMAPE_Fit=0.1491 SMAPE_Forecast=0.1376 SMAPE_Test=None
INFO:pyaf.std:MODEL_MASE MASE_Fit=0.6784 MASE_Forecast=0.5719 MASE_Test=None
INFO:pyaf.std:MODEL_L1 L1_Fit=0.5946639323035054 L1_Forecast=0.460502136109997 L1_Test=None
INFO:pyaf.std:MODEL_L2 L2_Fit=0.7992783835359704 L2_Forecast=0.598884966528019 L2_Test=None
INFO:pyaf.std:MODEL_COMPLEXITY 64
INFO:pyaf.std:SIGNAL_TRANSFORMATION_DETAIL_START
INFO:pyaf.std:SIGNAL_TRANSFORMATION_MODEL_VALUES NoTransf None
INFO:pyaf.std:SIGNAL_TRANSFORMATION_DETAIL_END
INFO:pyaf.std:TREND_DETAIL_START
INFO:pyaf.std:POLYNOMIAL_RIDGE_TREND PolyTrend (5.1221874309598405, array([-2.38954202, -0.38841589,  1.03620791]))
INFO:pyaf.std:TREND_DETAIL_END
INFO:pyaf.std:CYCLE_MODEL_DETAIL_START
INFO:pyaf.std:BEST_CYCLE_LENGTH_VALUES _Ozone_PolyTrend_residue_bestCycle_byMAPE None -0.036022548290779 {}
INFO:pyaf.std:CYCLE_MODEL_DETAIL_END
INFO:pyaf.std:AR_MODEL_DETAIL_START
INFO:pyaf.std:AR_MODEL_COEFF 1 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag1 0.40163635672211884
INFO:pyaf.std:AR_MODEL_COEFF 2 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag10 0.18633061162300973
INFO:pyaf.std:AR_MODEL_COEFF 3 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag12 0.17531425579039428
INFO:pyaf.std:AR_MODEL_COEFF 4 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag36 0.17375658201440333
INFO:pyaf.std:AR_MODEL_COEFF 5 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag7 -0.1646931589391768
INFO:pyaf.std:AR_MODEL_COEFF 6 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag30 0.14800975722350904
INFO:pyaf.std:AR_MODEL_COEFF 7 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag20 -0.11887274998925855
INFO:pyaf.std:AR_MODEL_COEFF 8 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag4 0.10707580719819529
INFO:pyaf.std:AR_MODEL_COEFF 9 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag48 0.10312520062123957
INFO:pyaf.std:AR_MODEL_COEFF 10 _Ozone_PolyTrend_residue_bestCycle_byMAPE_residue_Lag35 -0.10291731135870925
INFO:pyaf.std:AR_MODEL_DETAIL_END

In [5]:
model_no_cross_valid_forecast = model_no_cross_valid.forecast(ozone_dataframe, 12);
model_with_cross_valid_10_forecast = model_with_cross_valid_10.forecast(ozone_dataframe, 12);
model_with_cross_valid_5_forecast = model_with_cross_valid_5.forecast(ozone_dataframe, 12);


INFO:pyaf.std:START_FORECASTING 'Ozone'
INFO:pyaf.std:END_FORECAST_TIME_IN_SECONDS  'Ozone' 0.5515635013580322
INFO:pyaf.std:START_FORECASTING 'Ozone'
INFO:pyaf.std:END_FORECAST_TIME_IN_SECONDS  'Ozone' 0.5744578838348389
INFO:pyaf.std:START_FORECASTING 'Ozone'
INFO:pyaf.std:END_FORECAST_TIME_IN_SECONDS  'Ozone' 0.5695044994354248

In [6]:
model_no_cross_valid_forecast.plot.line('Month', ['Ozone' , 'Ozone_Forecast', 
                                             'Ozone_Forecast_Lower_Bound', 
                                             'Ozone_Forecast_Upper_Bound'], grid = True, figsize=(12, 8))
model_with_cross_valid_10_forecast.plot.line('Month', ['Ozone' , 'Ozone_Forecast', 
                                             'Ozone_Forecast_Lower_Bound', 
                                             'Ozone_Forecast_Upper_Bound'], grid = True, figsize=(12, 8))
model_with_cross_valid_5_forecast.plot.line('Month', ['Ozone' , 'Ozone_Forecast', 
                                             'Ozone_Forecast_Lower_Bound', 
                                             'Ozone_Forecast_Upper_Bound'], grid = True, figsize=(12, 8))


Out[6]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f204d8663a0>

In [ ]:


In [ ]: