← Back to Blog

Case Study - Predicting future sales

Sep 1, 2017 · WeifanD

最近小小参与了一场比赛,出题方是沃尔玛,题目是对其下45家零售店的销售进行预测。所提供的数据分为两部分,一部分是by store by department by week的销售数据,可以看作是时间序列数据,另一部分是markdown数据,这里可以把它看作影响销售量的特征。最后的评价标准是常用的criteria之一,WMAE,加权均化误差,也就是最后预测值与实际值之间的误差越小越好,WMAE值越小排位越高。

数据处理

原始的数据集是一个标准的 tidy dataset,即以行为 observation 列为 variable, 这里由于涉及到时间,结构相对特殊,是 time-store-department-sales 的 variable-value 结构。

Alt text

为了使时间成为一个unique key,我们需要对数据结构进行初步调整,其基本的概念是循环每一个部门,构造一个门店*时间的矩阵,相当于形成一系列门店的时间序列。

已知数据以周为单位,一年总共52周,沃尔玛是以周五为一周的最后一天。对于某些固定周几的假期来说,模型无需做调整。而圣诞节比较特殊,他只有固定日期,而周几却不同,这一点会很大的影响销量落在那一周。比如说2015年圣诞节是在第47周的周五,因而大量的盈利都发生在上个周六到这个周四之间,如预期第47周的销量非常高。那如果落在周六或周日,那他主要销量就会落在前一周。所以为了让销量更合理话,需要进行一个后延操作。如果48-51周的销量超过前后两周的10%,就后延一周;如果模型以去年为基准,后延2/7;由于测试集第一年后延两天,而第二年后延3天,所以如果以前两年为基准,后延2.5/7。

模型构建

基于R包forcast的现有时间序列模型以及几个原理简单的模型,分别对预测出的结果再进行postprocess操作。

时间序列模型总体基于不同的时间影响因素以及计算方式形成8种不同的模型,如下图。其中time factor包括trend和seasonality,calculation logic包括A(add)以及M(multiply)。 Alt text

对每个模型做简单的模型函数调用,然后合并。上部分代码:

stlf.svd <- function(train, test, model.type, n.comp){
  horizon <- nrow(test)
  train <- preprocess.svd(train, n.comp) 
  for(j in 2:ncol(train)){
    s <- ts(train[, j], frequency=52)
    if(model.type == 'ets'){
      fc <- stlf(s, 
                 h=horizon, 
                 s.window=3, 
                 method='ets',
                 ic='bic', 
                 opt.crit='mae')
    }else if(model.type == 'arima'){
      fc <- stlf(s, 
                 h=horizon, 
                 s.window=3, 
                 method='arima',
                 ic='bic')
    }else{
      stop('Model type must be one of ets or arima.')
    }
    pred <- as.numeric(fc$mean)
    test[, j] <- pred
  }
  test
}
#kaggle #Predicting