Skip to content

Commit

Permalink
Merge pull request #104 from antoinecarme/ts_cross_val
Browse files Browse the repository at this point in the history
Add the possibility to use cross validation when training PyAF models #105
  • Loading branch information
antoinecarme authored Sep 27, 2018
2 parents 362c968 + 6e7bacd commit 264106f
Show file tree
Hide file tree
Showing 88 changed files with 16,270 additions and 3,250 deletions.
10 changes: 9 additions & 1 deletion TS/Options.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ def disable_all_periodics(self):
def disable_all_autoregressions(self):
self.set_active_autoregressions([]);

class cCrossValidationOptions:
def __init__(self):
self.mMethod = None;
self.mNbFolds = 10


class cSignalDecomposition_Options(cModelControl):
Expand All @@ -101,7 +105,8 @@ def __init__(self):
super().__init__();
self.mParallelMode = True;
self.mNbCores = 8;
self.mEstimRatio = 0.8;
self.mEstimRatio = 0.8; # to be deprecated when cross validation is OK.
self.mCustomSplit = None
self.mAddPredictionIntervals = True
self.enable_fast_mode();
self.mTimeDeltaComputationMethod = "AVG"; # can be "AVG", "MODE", "USER"
Expand All @@ -118,6 +123,7 @@ def __init__(self):
self.mHierarchicalCombinationMethod = "BU";
self.mForecastRectifier = None # can be "relu" to force positive forecast values
self.mXGBOptions = None
self.mCrossValidationOptions = cCrossValidationOptions()
self.disableDebuggingOptions();

def disableDebuggingOptions(self):
Expand All @@ -142,6 +148,8 @@ def enable_slow_mode(self):

self.mMaxAROrder = 64;
self.mFilterSeasonals = False
# enable cross validation
self.mCrossValidationOptions.mMethod = "TSCV";

def enable_fast_mode(self):
self.mQuantiles = [5, 10, 20]; # quintiles, deciles, and vingtiles;)
Expand Down
7 changes: 4 additions & 3 deletions TS/PredictionIntervals.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,21 @@ def computePerformances(self):
lForecastColumn = str(self.mSignal) + "_Forecast";
df = self.mModel.mTrend.mSignalFrame.reset_index();
N = df.shape[0];
(lOriginalFit, lOriginalForecast, lOriginalTest) = self.mModel.mTimeInfo.cutFrame(df);
(lOriginalFit, lOriginalForecast, lOriginalTest) = self.mModel.mTimeInfo.mSplit.cutFrame(df);
df1 = df;
for h in range(0 , self.mHorizon):
df2 = None;
df2 = self.mModel.forecastOneStepAhead(df1, perf_mode = True);
df2 = df2.head(N);
lHorizonName = lForecastColumn + "_" + str(h + 1);
(lFrameFit, lFrameForecast, lFrameTest) = self.mModel.mTimeInfo.cutFrame(df2);
(lFrameFit, lFrameForecast, lFrameTest) = self.mModel.mTimeInfo.mSplit.cutFrame(df2);
self.mFitPerformances[lHorizonName] = tsperf.cPerf();
self.mFitPerformances[lHorizonName].compute(lOriginalFit[lSignalColumn], lFrameFit[lForecastColumn], lHorizonName);
self.mForecastPerformances[lHorizonName] = tsperf.cPerf();
self.mForecastPerformances[lHorizonName].compute(lOriginalForecast[lSignalColumn], lFrameForecast[lForecastColumn], lHorizonName);
self.mTestPerformances[lHorizonName] = tsperf.cPerf();
self.mTestPerformances[lHorizonName].compute(lOriginalTest[lSignalColumn], lFrameTest[lForecastColumn], lHorizonName);
if(lOriginalTest.shape[0] > 0):
self.mTestPerformances[lHorizonName].compute(lOriginalTest[lSignalColumn], lFrameTest[lForecastColumn], lHorizonName);
df1 = df2[[lTimeColumn , lForecastColumn]];
df1.columns = [lTimeColumn , lSignalColumn]
# self.dump_detailed();
Expand Down
14 changes: 7 additions & 7 deletions TS/Scikit_Models.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def fit(self):
series = self.mCycleResidueName;
self.mTime = self.mTimeInfo.mTime;
self.mSignal = self.mTimeInfo.mSignal;
lAREstimFrame = self.mTimeInfo.getEstimPart(self.mARFrame)
lAREstimFrame = self.mSplit.getEstimPart(self.mARFrame)

# print("mAREstimFrame columns :" , self.mAREstimFrame.columns);
lARInputs = lAREstimFrame[self.mInputNames].values
Expand Down Expand Up @@ -154,10 +154,10 @@ def build_Scikit_Model(self):

def set_name(self):
self.mOutName = self.mCycleResidueName + '_AR(' + str(self.mNbLags) + ")";
self.mFormula = "AR(" + str(self.mNbLags) + ")";
self.mFormula = "AR" # (" + str(self.mNbLags) + ")";
if(self.mExogenousInfo is not None):
self.mOutName = self.mCycleResidueName + '_ARX(' + str(self.mNbLags) + ")";
self.mFormula = "ARX(" + str(self.mNbExogenousLags) + ")";
self.mFormula = "ARX" # (" + str(self.mNbExogenousLags) + ")";



Expand All @@ -176,10 +176,10 @@ def build_Scikit_Model(self):

def set_name(self):
self.mOutName = self.mCycleResidueName + '_SVR(' + str(self.mNbLags) + ")";
self.mFormula = "SVR(" + str(self.mNbLags) + ")";
self.mFormula = "SVR" # (" + str(self.mNbLags) + ")";
if(self.mExogenousInfo is not None):
self.mOutName = self.mCycleResidueName + '_SVRX(' + str(self.mNbLags) + ")";
self.mFormula = "SVRX(" + str(self.mNbExogenousLags) + ")";
self.mFormula = "SVRX" # (" + str(self.mNbExogenousLags) + ")";


class cXGBoost_Model(cAbstract_Scikit_Model):
Expand Down Expand Up @@ -211,7 +211,7 @@ def build_Scikit_Model(self):

def set_name(self):
self.mOutName = self.mCycleResidueName + '_XGB(' + str(self.mNbLags) + ")";
self.mFormula = "XGB(" + str(self.mNbLags) + ")";
self.mFormula = "XGB" # + str(self.mNbLags) + ")";
if(self.mExogenousInfo is not None):
self.mOutName = self.mCycleResidueName + '_XGBX(' + str(self.mNbLags) + ")";
self.mFormula = "XGBX(" + str(self.mNbExogenousLags) + ")";
self.mFormula = "XGBX" # (" + str(self.mNbExogenousLags) + ")";
Loading

0 comments on commit 264106f

Please sign in to comment.