本次是用機器學習做出未來一定時期內的銷售量預測,從而輔助指導銷售庫存計劃的決策分析,以達到合理配置庫存,減少資源成本浪費的目的。實操內容有點多,雖然我已經儘量刪減了。有興趣的朋友可以關注+收藏,後面慢慢看喲。如果覺得內容還行,請多多鼓勵;如果有啥想法,評論留言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等;
- 模型超引數沒有調優,可以結合遺傳演算法搜尋最優超引數;
- 特徵工程過於粗糙,有必要了解具體業務知識創造特徵。
後面會對此次實踐做一些優化,可能需要再花上個幾天,如果有時間再將後續寫上來。一鍵三連~~