View source: R/AutoCatBoostCARMA.R
AutoCatBoostCARMA | R Documentation |
AutoCatBoostCARMA Mutlivariate Forecasting with calendar variables, Holiday counts, holiday lags, holiday moving averages, differencing, transformations, interaction-based categorical encoding using target variable and features to generate various time-based aggregated lags, moving averages, moving standard deviations, moving skewness, moving kurtosis, moving quantiles, parallelized interaction-based fourier pairs by grouping variables, and Trend Variables.
AutoCatBoostCARMA(
data,
TimeWeights = NULL,
NonNegativePred = FALSE,
RoundPreds = FALSE,
TrainOnFull = FALSE,
TargetColumnName = NULL,
DateColumnName = NULL,
HierarchGroups = NULL,
GroupVariables = NULL,
FC_Periods = 1,
TimeUnit = NULL,
TimeGroups = NULL,
SaveDataPath = NULL,
NumOfParDepPlots = 10L,
EncodingMethod = "target_encoding",
TargetTransformation = FALSE,
Methods = c("Asinh", "Log", "LogPlus1", "Sqrt"),
AnomalyDetection = NULL,
XREGS = NULL,
Lags = NULL,
MA_Periods = NULL,
SD_Periods = NULL,
Skew_Periods = NULL,
Kurt_Periods = NULL,
Quantile_Periods = NULL,
Quantiles_Selected = c("q5", "q95"),
Difference = FALSE,
FourierTerms = 0L,
CalendarVariables = NULL,
HolidayVariable = NULL,
HolidayLookback = NULL,
HolidayLags = NULL,
HolidayMovingAverages = NULL,
TimeTrendVariable = FALSE,
ZeroPadSeries = "maxmax",
DataTruncate = FALSE,
SplitRatios = c(0.85, 0.1, 0.05),
PartitionType = "random",
TaskType = "CPU",
NumGPU = 1,
DebugMode = FALSE,
Timer = TRUE,
EvalMetric = "RMSE",
EvalMetricValue = 1.2,
LossFunction = "RMSE",
LossFunctionValue = 1.2,
GridTune = FALSE,
PassInGrid = NULL,
ModelCount = 30,
MaxRunsWithoutNewWinner = 20,
MaxRunMinutes = 24L * 60L,
Langevin = FALSE,
DiffusionTemperature = 10000,
NTrees = 500,
L2_Leaf_Reg = 4,
LearningRate = 0.5,
RandomStrength = 1,
BorderCount = 254,
Depth = 6,
RSM = 1,
BootStrapType = "No",
GrowPolicy = "SymmetricTree",
ModelSizeReg = 1.2,
FeatureBorderType = "GreedyLogSum",
SamplingUnit = "Group",
SubSample = 0.7,
ScoreFunction = "Cosine",
MinDataInLeaf = 1,
ReturnShap = FALSE,
SaveModel = FALSE,
ArgsList = NULL,
ModelID = "FC001",
TVT = NULL
)
data |
Supply your full series data set here |
TimeWeights |
Supply a value that will be multiplied by he time trend value |
NonNegativePred |
TRUE or FALSE |
RoundPreds |
Rounding predictions to an integer value. TRUE or FALSE. Defaults to FALSE |
TrainOnFull |
Set to TRUE to train on full data |
TargetColumnName |
List the column name of your target variables column. E.g. 'Target' |
DateColumnName |
List the column name of your date column. E.g. 'DateTime' |
HierarchGroups |
Vector of hierachy categorical columns. |
GroupVariables |
Defaults to NULL. Use NULL when you have a single series. Add in GroupVariables when you have a series for every level of a group or multiple groups. |
FC_Periods |
Set the number of periods you want to have forecasts for. E.g. 52 for weekly data to forecast a year ahead |
TimeUnit |
List the time unit your data is aggregated by. E.g. '1min', '5min', '10min', '15min', '30min', 'hour', 'day', 'week', 'month', 'quarter', 'year'. |
TimeGroups |
Select time aggregations for adding various time aggregated GDL features. |
SaveDataPath |
NULL Or supply a path. Data saved will be called 'ModelID'_data.csv |
NumOfParDepPlots |
Supply a number for the number of partial dependence plots you want returned |
EncodingMethod |
'binary', 'credibility', 'woe', 'target_encoding', 'poly_encode', 'backward_difference', 'helmert' |
TargetTransformation |
TRUE or FALSE. If TRUE, select the methods in the Methods arg you want tested. The best one will be applied. |
Methods |
Choose from 'YeoJohnson', 'BoxCox', 'Asinh', 'Log', 'LogPlus1', 'Sqrt', 'Asin', or 'Logit'. If more than one is selected, the one with the best normalization pearson statistic will be used. Identity is automatically selected and compared. |
AnomalyDetection |
NULL for not using the service. Other, provide a list, e.g. AnomalyDetection = list('tstat_high' = 4, 'tstat_low' = -4) |
XREGS |
Additional data to use for model development and forecasting. Data needs to be a complete series which means both the historical and forward looking values over the specified forecast window needs to be supplied. |
Lags |
Select the periods for all lag variables you want to create. E.g. c(1:5,52) or list('day' = c(1:10), 'weeks' = c(1:4)) |
MA_Periods |
Select the periods for all moving average variables you want to create. E.g. c(1:5,52) or list('day' = c(2:10), 'weeks' = c(2:4)) |
SD_Periods |
Select the periods for all moving standard deviation variables you want to create. E.g. c(1:5,52) or list('day' = c(2:10), 'weeks' = c(2:4)) |
Skew_Periods |
Select the periods for all moving skewness variables you want to create. E.g. c(1:5,52) or list('day' = c(2:10), 'weeks' = c(2:4)) |
Kurt_Periods |
Select the periods for all moving kurtosis variables you want to create. E.g. c(1:5,52) or list('day' = c(2:10), 'weeks' = c(2:4)) |
Quantile_Periods |
Select the periods for all moving quantiles variables you want to create. E.g. c(1:5,52) or list('day' = c(2:10), 'weeks' = c(2:4)) |
Quantiles_Selected |
Select from the following 'q5', 'q10', 'q15', 'q20', 'q25', 'q30', 'q35', 'q40', 'q45', 'q50', 'q55', 'q60', 'q65', 'q70', 'q75', 'q80', 'q85', 'q90', 'q95' |
Difference |
Puts the I in ARIMA for single series and grouped series. |
FourierTerms |
Set to the max number of pairs. E.g. 2 means to generate two pairs for by each group level and interations if hierarchy is enabled. |
CalendarVariables |
NULL, or select from 'minute', 'hour', 'wday', 'mday', 'yday', 'week', 'isoweek', 'month', 'quarter', 'year' |
HolidayVariable |
NULL, or select from 'USPublicHolidays', 'EasterGroup', 'ChristmasGroup', 'OtherEcclesticalFeasts' |
HolidayLookback |
Number of days in range to compute number of holidays from a given date in the data. If NULL, the number of days are computed for you. |
HolidayLags |
Number of lags to build off of the holiday count variable. |
HolidayMovingAverages |
Number of moving averages to build off of the holiday count variable. |
TimeTrendVariable |
Set to TRUE to have a time trend variable added to the model. Time trend is numeric variable indicating the numeric value of each record in the time series (by group). Time trend starts at 1 for the earliest point in time and increments by one for each success time point. |
ZeroPadSeries |
NULL to do nothing. Otherwise, set to 'maxmax', 'minmax', 'maxmin', 'minmin'. See |
DataTruncate |
Set to TRUE to remove records with missing values from the lags and moving average features created |
SplitRatios |
E.g c(0.7,0.2,0.1) for train, validation, and test sets |
PartitionType |
Select 'random' for random data partitioning 'timeseries' for partitioning by time frames |
TaskType |
Default is 'GPU' but you can also set it to 'CPU' |
NumGPU |
Defaults to 1. If CPU is set this argument will be ignored. |
DebugMode |
Defaults to FALSE. Set to TRUE to get a print statement of each high level comment in function |
Timer |
Set to FALSE to turn off the updating print statements for progress |
EvalMetric |
Select from 'RMSE', 'MAE', 'MAPE', 'Poisson', 'Quantile', 'LogLinQuantile', 'Lq', 'NumErrors', 'SMAPE', 'R2', 'MSLE', 'MedianAbsoluteError' |
EvalMetricValue |
Used when EvalMetric accepts an argument. See |
LossFunction |
Used in model training for model fitting. Select from 'RMSE', 'MAE', 'Quantile', 'LogLinQuantile', 'MAPE', 'Poisson', 'PairLogitPairwise', 'Tweedie', 'QueryRMSE' |
LossFunctionValue |
Used when LossFunction accepts an argument. See |
GridTune |
Set to TRUE to run a grid tune |
PassInGrid |
Defaults to NULL |
ModelCount |
Set the number of models to try in the grid tune |
MaxRunsWithoutNewWinner |
Default is 50 |
MaxRunMinutes |
Default is 60*60 |
Langevin |
Enables the Stochastic Gradient Langevin Boosting mode. If TRUE and TaskType == 'GPU' then TaskType will be converted to 'CPU' |
DiffusionTemperature |
Default is 10000 |
NTrees |
Select the number of trees you want to have built to train the model |
L2_Leaf_Reg |
l2 reg parameter |
LearningRate |
Defaults to NULL. Catboost will dynamically define this if L2_Leaf_Reg is NULL and RMSE is chosen (otherwise catboost will default it to 0.03). Then you can pull it out of the model object and pass it back in should you wish. |
RandomStrength |
Default is 1 |
BorderCount |
Default is 254 |
Depth |
Depth of catboost model |
RSM |
CPU only. If TaskType is GPU then RSM will not be used |
BootStrapType |
If NULL, then if TaskType is GPU then Bayesian will be used. If CPU then MVS will be used. If MVS is selected when TaskType is GPU, then BootStrapType will be switched to Bayesian |
GrowPolicy |
Default is SymmetricTree. Others include Lossguide and Depthwise |
ModelSizeReg |
Defaults to 0.5. Set to 0 to allow for bigger models. This is for models with high cardinality categorical features. Valuues greater than 0 will shrink the model and quality will decline but models won't be huge. |
FeatureBorderType |
Defaults to 'GreedyLogSum'. Other options include: Median, Uniform, UniformAndQuantiles, MaxLogSum, MinEntropy |
SamplingUnit |
Default is Group. Other option is Object. if GPU is selected, this will be turned off unless the loss_function is YetiRankPairWise |
SubSample |
Can use if BootStrapType is neither Bayesian nor No. Pass NULL to use Catboost default. Used for bagging. |
ScoreFunction |
Default is Cosine. CPU options are Cosine and L2. GPU options are Cosine, L2, NewtonL2, and NewtomCosine (not available for Lossguide) |
MinDataInLeaf |
Defaults to 1. Used if GrowPolicy is not SymmetricTree |
SaveModel |
Logical. If TRUE, output ArgsList will have a named element 'Model' with the CatBoost model object |
ArgsList |
ArgsList is for scoring. Must contain named element 'Model' with a catboost model object |
ModelID |
Something to name your model if you want it saved |
TVT |
Passthrough |
ExpandEncoding |
= FALSE |
See examples
Adrian Antico
Other Automated Panel Data Forecasting:
AutoH2OCARMA()
,
AutoLightGBMCARMA()
,
AutoXGBoostCARMA()
## Not run:
# Set up your output file path for saving results as a .csv
Path <- 'C:/YourPathHere'
# Run on GPU or CPU (some options in the grid tuning force usage of CPU for some runs)
TaskType = 'GPU'
# Define number of CPU threads to allow data.table to utilize
data.table::setDTthreads(percent = max(1L, parallel::detectCores()-2L))
# Load data
data <- data.table::fread('https://www.dropbox.com/s/2str3ek4f4cheqi/walmart_train.csv?dl=1')
data <- Rappture::DM.pgQuery(Host = 'localhost', DataBase = 'AutoQuant', SELECT = NULL, FROM = 'WalmartFull', User = 'postgres', Port = 5432, Password = 'Aa1028#@')
# Ensure series have no missing dates (also remove series with more than 25% missing values)
data <- AutoQuant::TimeSeriesFill(
data,
DateColumnName = 'Date',
GroupVariables = c('Store','Dept'),
TimeUnit = 'weeks',
FillType = 'maxmax',
MaxMissingPercent = 0.25,
SimpleImpute = TRUE)
# Set negative numbers to 0
data <- data[, Weekly_Sales := data.table::fifelse(Weekly_Sales < 0, 0, Weekly_Sales)]
# Remove IsHoliday column
data[, IsHoliday := NULL]
# Create xregs (this is the include the categorical variables instead of utilizing only the interaction of them)
xregs <- data[, .SD, .SDcols = c('Date', 'Store', 'Dept')]
# Change data types
data[, ':=' (Store = as.character(Store), Dept = as.character(Dept))]
xregs[, ':=' (Store = as.character(Store), Dept = as.character(Dept))]
# Subset data so we have an out of time sample
data1 <- data.table::copy(data[, ID := 1L:.N, by = c('Store','Dept')][ID <= 125L][, ID := NULL])
data[, ID := NULL]
# Define values for SplitRatios and FCWindow Args
N1 <- data1[, .N, by = c('Store','Dept')][1L, N]
N2 <- xregs[, .N, by = c('Store','Dept')][1L, N]
# Setup Grid Tuning & Feature Tuning data.table using a cross join of vectors
Tuning <- data.table::CJ(
TimeWeights = c('None',0.999),
MaxTimeGroups = c('weeks','months'),
TargetTransformation = c('TRUE','FALSE'),
Difference = c('TRUE','FALSE'),
HoldoutTrain = c(6,18),
Langevin = c('TRUE','FALSE'),
NTrees = c(2500,5000),
Depth = c(6,9),
RandomStrength = c(0.75,1),
L2_Leaf_Reg = c(3.0,4.0),
RSM = c(0.75,'NULL'),
GrowPolicy = c('SymmetricTree','Lossguide','Depthwise'),
BootStrapType = c('Bayesian','MVS','No'))
# Remove options that are not compatible with GPU (skip over this otherwise)
Tuning <- Tuning[Langevin == 'TRUE' | (Langevin == 'FALSE' & RSM == 'NULL' & BootStrapType %in% c('Bayesian','No'))]
# Randomize order of Tuning data.table
Tuning <- Tuning[order(runif(.N))]
# Load grid results and remove rows that have already been tested
if(file.exists(file.path(Path, 'Walmart_CARMA_Metrics.csv'))) {
Metrics <- data.table::fread(file.path(Path, 'Walmart_CARMA_Metrics.csv'))
temp <- data.table::rbindlist(list(Metrics,Tuning), fill = TRUE)
temp <- unique(temp, by = c(4:(ncol(temp)-1)))
Tuning <- temp[is.na(RunTime)][, .SD, .SDcols = names(Tuning)]
rm(Metrics,temp)
}
# Define the total number of runs
TotalRuns <- Tuning[,.N]
# Kick off feature + grid tuning
for(Run in seq_len(TotalRuns)) {
# print run number
for(zz in seq_len(100)) print(Run)
# Use fresh data for each run
xregs_new <- data.table::copy(xregs)
data_new <- data.table::copy(data1)
# Timer start
StartTime <- Sys.time()
# Run carma system
CatBoostResults <- AutoQuant::AutoCatBoostCARMA(
# data args
data = data_new,
TimeWeights = if(Tuning[Run, TimeWeights] == 'None') NULL else as.numeric(Tuning[Run, TimeWeights]),
TargetColumnName = 'Weekly_Sales',
DateColumnName = 'Date',
HierarchGroups = NULL,
GroupVariables = c('Store','Dept'),
EncodingMethod = 'credibility',
TimeUnit = 'weeks',
TimeGroups = if(Tuning[Run, MaxTimeGroups] == 'weeks') 'weeks' else if(Tuning[Run, MaxTimeGroups] == 'months') c('weeks','months') else c('weeks','months','quarters'),
# Production args
TrainOnFull = TRUE,
SplitRatios = c(1 - Tuning[Run, HoldoutTrain] / N2, Tuning[Run, HoldoutTrain] / N2),
PartitionType = 'random',
FC_Periods = N2-N1,
TaskType = TaskType,
NumGPU = 1,
Timer = TRUE,
DebugMode = TRUE,
# Target variable transformations
TargetTransformation = as.logical(Tuning[Run, TargetTransformation]),
Methods = c('YeoJohnson', 'BoxCox', 'Asinh', 'Log', 'LogPlus1', 'Sqrt', 'Asin', 'Logit'),
Difference = as.logical(Tuning[Run, Difference]),
NonNegativePred = TRUE,
RoundPreds = FALSE,
# Calendar-related features
CalendarVariables = c('week','wom','month','quarter'),
HolidayVariable = c('USPublicHolidays'),
HolidayLookback = NULL,
HolidayLags = c(1,2,3),
HolidayMovingAverages = c(2,3),
# Lags, moving averages, and other rolling stats
Lags = if(Tuning[Run, MaxTimeGroups] == 'weeks') c(1,2,3,4,5,8,9,12,13,51,52,53) else if(Tuning[Run, MaxTimeGroups] == 'months') list('weeks' = c(1,2,3,4,5,8,9,12,13,51,52,53), 'months' = c(1,2,6,12)) else list('weeks' = c(1,2,3,4,5,8,9,12,13,51,52,53), 'months' = c(1,2,6,12), 'quarters' = c(1,2,3,4)),
MA_Periods = if(Tuning[Run, MaxTimeGroups] == 'weeks') c(2,3,4,5,8,9,12,13,51,52,53) else if(Tuning[Run, MaxTimeGroups] == 'months') list('weeks' = c(2,3,4,5,8,9,12,13,51,52,53), 'months' = c(2,6,12)) else list('weeks' = c(2,3,4,5,8,9,12,13,51,52,53), 'months' = c(2,6,12), 'quarters' = c(2,3,4)),
SD_Periods = NULL,
Skew_Periods = NULL,
Kurt_Periods = NULL,
Quantile_Periods = NULL,
Quantiles_Selected = NULL,
# Bonus features
AnomalyDetection = NULL,
XREGS = xregs_new,
FourierTerms = 0,
TimeTrendVariable = TRUE,
ZeroPadSeries = NULL,
DataTruncate = FALSE,
# ML grid tuning args
GridTune = FALSE,
PassInGrid = NULL,
ModelCount = 5,
MaxRunsWithoutNewWinner = 50,
MaxRunMinutes = 60*60,
# ML evaluation output
SaveDataPath = NULL,
NumOfParDepPlots = 0L,
# ML loss functions
EvalMetric = 'RMSE',
EvalMetricValue = 1,
LossFunction = 'RMSE',
LossFunctionValue = 1,
# ML tuning args
NTrees = Tuning[Run, NTrees],
Depth = Tuning[Run, Depth],
L2_Leaf_Reg = Tuning[Run, L2_Leaf_Reg],
LearningRate = 0.03,
Langevin = as.logical(Tuning[Run, Langevin]),
DiffusionTemperature = 10000,
RandomStrength = Tuning[Run, RandomStrength],
BorderCount = 254,
RSM = if(Tuning[Run, RSM] == 'NULL') NULL else as.numeric(Tuning[Run, RSM]),
GrowPolicy = Tuning[Run, GrowPolicy],
BootStrapType = Tuning[Run, BootStrapType],
ModelSizeReg = 0.5,
FeatureBorderType = 'GreedyLogSum',
SamplingUnit = 'Group',
SubSample = NULL,
ScoreFunction = 'Cosine',
MinDataInLeaf = 1)
# Timer End
EndTime <- Sys.time()
# Prepare data for evaluation
Results <- CatBoostResults$Forecast
data.table::setnames(Results, 'Weekly_Sales', 'bla')
Results <- merge(Results, data, by = c('Store','Dept','Date'), all = FALSE)
Results <- Results[is.na(bla)][, bla := NULL]
# Create totals and subtotals
Results <- data.table::groupingsets(
x = Results,
j = list(Predictions = sum(Predictions), Weekly_Sales = sum(Weekly_Sales)),
by = c('Date', 'Store', 'Dept'),
sets = list(c('Date', 'Store', 'Dept'), c('Store', 'Dept'), 'Store', 'Dept', 'Date'))
# Fill NAs with 'Total' for totals and subtotals
for(cols in c('Store','Dept')) Results[, eval(cols) := data.table::fifelse(is.na(get(cols)), 'Total', get(cols))]
# Add error measures
Results[, Weekly_MAE := abs(Weekly_Sales - Predictions)]
Results[, Weekly_MAPE := Weekly_MAE / Weekly_Sales]
# Weekly results
Weekly_MAPE <- Results[, list(Weekly_MAPE = mean(Weekly_MAPE)), by = list(Store,Dept)]
# Monthly results
temp <- data.table::copy(Results)
temp <- temp[, Date := lubridate::floor_date(Date, unit = 'months')]
temp <- temp[, lapply(.SD, sum), by = c('Date','Store','Dept'), .SDcols = c('Predictions', 'Weekly_Sales')]
temp[, Monthly_MAE := abs(Weekly_Sales - Predictions)]
temp[, Monthly_MAPE := Monthly_MAE / Weekly_Sales]
Monthly_MAPE <- temp[, list(Monthly_MAPE = mean(Monthly_MAPE)), by = list(Store,Dept)]
# Collect metrics for Total (feel free to switch to something else or no filter at all)
Metrics <- data.table::data.table(
RunNumber = Run,
Total_Weekly_MAPE = Weekly_MAPE[Store == 'Total' & Dept == 'Total', Weekly_MAPE],
Total_Monthly_MAPE = Monthly_MAPE[Store == 'Total' & Dept == 'Total', Monthly_MAPE],
Tuning[Run],
RunTime = EndTime - StartTime)
# Append to file (not overwrite)
data.table::fwrite(Metrics, file = file.path(Path, 'Walmart_CARMA_Metrics.csv'), append = TRUE)
# Remove objects (clear space before new runs)
rm(CatBoostResults, Results, temp, Weekly_MAE, Weekly_MAPE, Monthly_MAE, Monthly_MAPE)
# Garbage collection because of GPU
gc()
}
## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.