今回予測の目的は現職で販売をしており、時系列データで予測を行うことにより自店舗の売り上げ予測も出来ると考えまずは練習として自分の好物のピザで売上予測をしてみました。 機械学習の勉強を始めて6ヶ月が経地ましたが実際のデータでモデル構築は経験していなかった為、不安ですがこれまでの経験も活かしつつ、これから機械学習を勉強する人への参考記事にもなったら良いなと思っています。
目次
はじめに
自己紹介
データの中身
実行環境
データの状態
必要モジュール
1.データの読み込み
2.データの整理
orderの最適化関数
モデルの構築
結果
まとめ
はじめに
初めまして。転職を考えるうちに自分の人生や働き方について深く考えるようになりました。異業種にチャレンジしたいという気持ちが強くなりプログラミングを学ぶことから始めました。初心者ですがどうぞ宜しくお願い致します。
自己紹介
1歳半の息子が居るサラリーマンパパです。
progate等でコードを開いてみたりしましたが本格的な勉強は初めてになります。
アイデミーデータ分析講座にてプログラミングを勉強中です
目的
私は雪国新潟の出身で毎年必ず雪が降ります。しかし積雪量というのは毎年異なり、腰の高さまで降る年もあれば、除雪が必要のない位少ない年もあります。最近の積雪量は異常気象により予測が難しいものとなっておりますが、今年の積雪も気になるところではありますので積雪量が予測できるようにしていきたいと思います。
データの中身
【期間】2015年1月~2015年12月までのピザの売上枚数
実行環境
Google Colaboratory
データの状態
データはkaggleからダウンロードしました。
info
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 48620 entries, 0 to 48619
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 order_details_id 48620 non-null int64
1 order_id 48620 non-null int64
2 pizza_id 48620 non-null object
3 quantity 48620 non-null int64
4 order_date 48620 non-null datetime64[ns]
5 order_time 48620 non-null object
6 unit_price 48620 non-null float64
7 total_price 48620 non-null float64
8 pizza_size 48620 non-null object
9 pizza_category 48620 non-null object
10 pizza_ingredients 48620 non-null object
11 pizza_name 48620 non-null object
dtypes: datetime64[ns](1), float64(2), int64(3), object(6)
memory usage: 4.5+ MB
必要モジュール
まずは必要なモジュールをimportします。実行環境に以下のコードを書きます。
importコード
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
import missingno as msno
1.データの読み込み
Excelデータの為、pandasを用いて読み込みます。
コード
df = pd.read_excel('/content/Data Model - Pizza Sales.xlsx')
2.データの整理
まずは欠損している部分を確認します。
コード
df.isnull().sum()
結果
order_details_id 0
order_id 0
pizza_id 0
quantity 0
order_date 0
order_time 0
unit_price 0
total_price 0
pizza_size 0
pizza_category 0
pizza_ingredients 0
pizza_name 0
dtype: int64
分かりやすくカラムを'Date'に変換し必要な日付とピザの売上枚数に限定します。
コード
df = df.rename(columns={'order_date': 'Date'})
df= df[["Date","quantity"]]
一度可視化してみます。
コード
plt.plot(df["Date"], df["quantity"])
plt.show()
すでにデータの学習を行なっている為、学習データとテストデータで分けたいと思います。
コード
thresh = int(len(df)*0.9)
train_df = df[:thresh]
test_df = df[thresh:]
ここで欠損している日にちがあった為前日の売上で補う事とします。
コード
df['Date'] = pd.to_datetime(df['Date'])
df = df.set_index('Date')
# 一日刻みのindexを作成する
index = pd.date_range('2015-01-01 ', '2015-12-31', freq='D')
# dummyデータを作成し、dfと結合することで、どこが欠損しているのかを把握する
dummy_df = pd.DataFrame([0]*len(index),index=index,columns=["dummy"])
merge_df = pd.merge(dummy_df, df,left_index=True,right_index=True,how="outer")
print(merge_df[merge_df['quantity'].isnull()==True].index)
#欠損日付一覧['2015-09-24', '2015-09-25', '2015-10-05', '2015-10-12','2015-10-19', '2015-10-26', '2015-12-25']
# 今回は一つ前の値で補うこととする
df = merge_df["quantity"].ffill()
orderの最適化関数
ここでパラメータを選択するために、時系列データ:DATA, パラメータs(周期):sを入力すると、最も良いパラメーターとそのBICを出力するselectparameteという関数を定義していきます。
コード
def selectparameter(DATA, s):
p = d = q = range(0, 2)
pdq = list(itertools.product(p, d, q))
seasonal_pdq = [(x[0], x[1], x[2], s) for x in list(itertools.product(p, d, q))]
parameters = []
BICs = np.array([])
for param in pdq:
for param_seasonal in seasonal_pdq:
try:
mod = sm.tsa.statespace.SARIMAX(DATA,
order=param,
seasonal_order=param_seasonal)
results = mod.fit()
parameters.append([param, param_seasonal, results.bic])
BICs = np.append(BICs, results.bic)
except:
continue
return parameters[np.argmin(BICs)]
モデルの構築
いよいよモデルの構築です。
時系列データ解析について
「ピザの売り上げ予測のモデル構築」は、時系列データ解析に該当します。時系列データとは、時間の経過と共に変化するデータのことを指します。時系列データ解析は、会社の売り上げや商品の売り上げの予測にも応用できるので、ビジネスシーンでも非常に重要な分析技術とされています。
モデルの紹介
今回トレンドと季節性があるデータはSARIMAモデルというモデルで表現することができる為、SARIMAで予測を行いますが、
その他のモデルも紹介します。
MAモデル
単に時系列が異なる式との間に共通部分を持つために相関性が存在するという性質を持つモデル
ARモデル
過去の値から回帰的にある時点の値を推定するモデル
ARMAモデル
ARMAモデル とはその名前の通り後述する ARモデル と MAモデル をあわせたモデルになります。AR(p)のARモデルとMA(q)のMAモデルを組み合わせたときARMA(p,q)のように表すことができます。定常過程にしか適応できません。
ARIMAモデル
非定常過程の原系列の差分をとり、ARMAモデルを適応したモデルをARIMAモデルという
先程のARMAモデルへ原系列を階差系列に変換し適応したものをARIMAモデルと言います。非定常過程(データの平均や分散が時間に依存している過程)にも適応可能です。d時点前との差分をとった場合のARMA(p,q)で構築したARIMAモデルをARIMA(p,d,q)と表します。
pを自己相関度 モデルが直前 p 個の値を用いて予測されるのか を
dを誘導 時系列データを定常にするために d 次の階差が必要だったこと を
qを 移動平均 モデルが直前 q 個の値に影響を受けること を表しています。
SARIMAモデル
ARIMAモデルは(p,d,q)をさらに季節周期を持つ時系列データにも拡張できるようにしたモデルです。SARIMAモデルは(p, d, q)のパラメーターに加えて(sp, sd, sq, s)というパラメーターも持ちます。
sp:季節性自己相関
sd:季節性導出,
sq: 季節性移動平均
上記を踏まえ季節周期を持つ時系列データにも拡張できるようにしたモデルの為、SARIMAで今回は予測していきます。
コード
# 周期は月ごとのデータであることも考慮してs=12となります
# orderはselectparameter関数の0インデックス, seasonal_orderは1インデックスに格納されています
best_params = selectparameter(train_df, 12)
model = sm.tsa.statespace.SARIMAX(train_df, order=best_params[0],
seasonal_order=best_params[1],
enforce_stationarity=False, enforce_invertibility=False).fit()
結果
予測と可視化
下記コードで期間を定め可視化します。
コード
# predに予測期間での予測値を代入
pred = model.predict("2015-11-25", "2015-12-31")
# グラフを可視化。予測値は赤色でプロット。
plt.plot(df)
plt.plot(pred, "r")
plt.show()
結果
なんとかメンターの方の補助のおかげで予測することが出来ました。
赤色が予測になりますがなんとなく予測はできていると感じました。今回のデータが1年しかない為質の高いデータではないですがうまく予測ができたと思います。
まとめ
今まで売上の向上する理由など知る余地も無かった為、もっと知りたい。色々なデータで試してみたいと感じました。
今回時系列の予測に関して骨が折れそうになることが難度もあり、メンターの方には質問攻めすることが何度もございました。
自分の将来の為にも今回の講座をより一層理解できる様自分自身で探求し今後に繋げていきたいと思います。
最後までご覧いただきありがとうございました。