本次是用機器學習做出未來一定時期內的銷售量預測,從而輔助指導銷售庫存計划的決策分析,以達到合理配置庫存,減少資源成本浪費的目的。實操內容有點多,雖然我已經盡量刪減了。有興趣的朋友可以關注+收藏,后面慢慢看喲。如果覺得內容還行,請多多鼓勵;如果有啥想法,評論留言or私信。那么我們開始說正事了~
一、數據准備階段
數據集描述
用於技術驗證的數據集來自kaggle上的醫葯銷售預測項目Rossmann Stores Clustering and Forecast,整個數據集包含三張表:訓練集、測試集、經銷商信息表。測試集只比訓練集少銷售額Sales和Customers這兩個字段,其它字段完全相同,其中訓練集和測試集分別有1017209和41088條,訓練集和測試集前五條數據如下。
測試集包含未來六周的促銷等狀況,要求預測指定經銷商的銷售額或則顧客總數。
經銷商信息數據集store.csv有1115條數據,也就是1115家經銷商,10個字段。
其中Store字段唯一代表一家經銷商,可以將train.csv和test.csv分別與store.csv通過字段Store關聯起來。
數據預處理
1. 首先從日期字段Date中提取出年月日以及該日期在所在年的第幾周,並將它們作為新的字段,方便之后對數據按時間進行聚合處理。
2. 對三張表中的分類變量進行編碼轉換,采用sklearn內置的LabelEncoder編碼。
3. 查看每張表的字段缺失情況,train.csv,test.csv,store.csv缺失如下
在store表中,缺失字段CompetitionDistance表示最近競爭對手的距離,是一個連續變量,用中位值填充該變量的缺失值,其它的確實變量統統用0填充。對於test表中有11條變量確實Open字段,表面其沒有開業,在后面的建模中會被直接過濾掉,此處暫不處理。
4. 合並字段CompetitionOpenSinceMonth表示距離最近的競爭對手開業的月份,CompetitionOpenSinceYear則表示開業的年份,構造字段CompetitionOpenSince表示競爭對手開業以來的總的月份;Promo2SinceYear/ Promo2SinceWeek表示商店參與最近促銷的年份和參與時間所在的周,構造字段Promo2Since表示商家參與促銷以來所經歷的周數,根據經驗Promo2Since與Promo會呈現負相關性,因為當前促銷Promo和之前促銷存在競爭關系。
相關性分析
進行變量之間的相關性分析,選取具有代表性的促銷相關的變量Promo,Promo2,Promo2Since,以及與競爭相關的變量CompetitionDistance,CompetitionOpenSince,做出它們的散點圖,如下
從圖中可以發現無論對於哪一種類型的經銷商,當前促銷Promo能夠明顯提升當前的銷量,而之前的促銷Promo2則會降低當前的銷量,並且當前促銷后銷量會在周一達到峰值,另外可以發現當前促銷的商家在周六和周日都不開門,第三種類型的商家在周日一直都不開門,第四種商家在當前不促銷之前促銷時在周日不開門。
同時也做出促銷對銷量在月份上的影響,如下
可以發現所有商家在年底的銷量達到頂峰,表面月份對銷量有顯著的影響。
最后做出所有變量的相關系數矩陣,如下所示
發現Weekofyear和Month,Promo2和PromoInterval相關性非常之高,於是建模時舍棄Month和PromoInterval,其余變量全部用於建立機器學習模型。
二、建模
建立的模型主要建立包括三類:時間序列模型、機器學習模型、深度學習模型。
時間序列ARIMA模型
銷售數據是典型的時間序列數據,對銷售數據建立時間序列模型需要檢驗數據的平穩性,趨勢性。建模的數據為所有經銷商每天的銷售總額,為了避免數據波動過大,對原數據取對數,平穩性檢驗采用最常用的adfuller單位根檢驗,結果如下
P值非常之小,在99%的置信水平上認為該序列是平穩的。如若不平穩,則可以進行差分運算直至平穩為止,不過通常做3差分后已經平穩。
通過某些方法,例如傅里葉分解、小波分解、TSI分解等,將數據分解成可預測部分和不規則變動(隨機波動)部分,可預測部分占比比不規則變動大很多,那么就具備了預測未來的條件。為了查看其趨勢性,采用TSI分解,即將時間序列分解成趨勢trend,季節周期性seasonal,隨機部分residual這三個部分,然后對trend部分建立時間序列模型,然后加上seasonal作為預測值,residual因為是隨機的,不能預測。對銷量數據進行分解后的效果如下
不難發現沒有明顯的趨勢性,呈現波動狀態,seasonal部分放大了后發現周期為7,殘差部分residual存在毛刺,這可能與促銷或者節假日有關,暫且按下不表,先檢驗residual的平穩性,結果如下
P值十分之小,在99%的置信度下是平穩的。下面用ARIMA模型對trend部分建立模型,確定其AR,MA的階數都為4,另外沒有做差分,所以最終的階數為order=(4,0,4),對trend的擬合效果如下
加上seasonal部分在進行指數還原后結果如下
對時間序列按照7:3划分為訓練集和測試集,並且將原始數據和預測數據按照7天進行降采樣求和,看出在驗證集上的RMSE挺大的,意味着存在很大的預測偏差,達到21%。
機器學習模型
將數據集按照7:3的比例划分為訓練集和測試集,分別采用了GBT,Xgboost,LightGBM,RandomForest這三種預測准確度比較高的樹模型進行預測,預測效果分別如下
驗證集上的平均預測誤差為10.91%,
驗證集上的平均預測誤差為5.57%,
驗證集上的平均預測誤差為8.57%。
最后選擇預測效果最好的Xgboost作為最終的機器學習模型進行銷量的預測,給銷量預測設置一個預測區間,當預測銷量不在區間范圍時,廠商或者經銷商就應該相應進行庫存調整或者促銷方案或者銷售人員的安排做出變動。預測區間根據預測值的四分位數確定,預測上線為Q3+k1(Q3-Q1),下線為Q1-k2(Q3-Q1),其中k1,k2的值由商家的庫存狀況自行確定。加上預測區間后的預測效果如下
以上內容是對整個公司所有經銷商的銷售量進行預測,接下來對不同類型的經銷商的銷售量進行預測,為此把經銷商分成5種類型,采用層次聚類,效果如下
類型種數根據實際情況指定,然后可以按類別分別建模,除此之外,還可以按照每家經銷商建立模型。於是,可以給出總銷量,某種類型或者某家經銷商的銷量預測。如下圖,給出了這家經銷商未來六周的銷售量預測值,以及預測區間,其中金色線為預測上限,土黃色線為預測下限
三、后記
實踐總結發現仍然存在一些需要改進的地方,主要有以下幾點:
- 模型的預測偏差還是比較大,應該適當改進模型,比如進行模型融合,采用DNN等;
- 模型超參數沒有調優,可以結合遺傳算法搜索最優超參數;
- 特征工程過於粗糙,有必要了解具體業務知識創造特征。
后面會對此次實踐做一些優化,可能需要再花上個幾天,如果有時間再將后續寫上來。一鍵三連~~