【Python初心者】時系列解析の学習を通してして、オンラインビジネスの売上を予測してみました。

はじめに

この度、産休期間を利用してAidemy Premiumにて「データ分析 3カ月コース」を受講いたしました。

現職に生かしつつ、勉強を今後も進めて今後のキャリアアップや転職の可能性にも生かせるか探っていきたいと思っています。

※このブログはAidemy Premiumのカリキュラムの一環で、受講修了条件を満たすために公開しています。

実行環境

Google Colaboratory

分析の流れ

時系列解析(SARIMAモデル)を使用して、下記の流れで売上予測を行います。
SARIMAモデルとはARIMAモデルをさらに季節周期を持つ時系列データにも拡張できるようにしたモデルです。SARIMAモデルはARIMAモデルの時系列(p, d, q)のパラメーターに加えて季節差分と周期(sp, sd, sq, s)というパラメーターも持ちます。
簡単に言うと季節性の影響を受けるデータにおいて時間の経過と共に変化するデータパターンを捉えます。

今回は下記の流れで時系列解析を進めます。

1.環境構築とデータの読み込み
2.データ前整理
3.データの可視化
4.パラメータの決定
5.モデルの予測と可視化

1.環境構築とデータの読み込み

データ分析に必要なライブラリをインポートします。

#ライブラリの読み込み
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import itertools
import statsmodels.api as sm

今回はKaggleにて公開されているデータセットを利用していきます。
(https://www.kaggle.com/datasets/gabrielramos87/an-online-shop-business)

#Kaggleのデータを参照(https://www.kaggle.com/datasets/gabrielramos87/an-online-shop-business)
df = pd.read_csv('drive/My Drive/Sales Transaction v.4a.csv')

df

データを確認すると下記の様になっています。

出力結果

各インデックスのデータ型もチェックします。

df.dtypes
出力結果

2.データ前整理

上記にてDateの表記がobject型になっているためdatetime型へ変換していきます。
合わせてDate列をIndexへ割り当てたあと、再度dfに代入します。

df["Date"] = pd.to_datetime(df["Date"])
df.set_index('Date')
df=df.set_index('Date')

今回の分析のターゲットとするQuantityの中身を見ていきます。

df["Quantity"]
出力結果

今回は週毎に売上をまとめて分析を進めます。
元データは日別売上が何行もあります。週毎にまとめる為今回はresmapleを使用。

df2=df["Quantity"].resample("W").mean()
df2

週毎にまとまりました。
2018-12-30週が欠損値になっています。

出力結果

欠損値にの補完を行います。欠損値をその列の平均値によって穴埋めをする平均値代入法を使用。

df3 = df2.fillna(df2.mean())

欠損値の補完ができたので最後にデータを確認していきます。

index = pd.date_range("2018-12-02", "2019-12-21", freq = "W")
df3.index = index
print(df3.head())
出力結果

3.データの可視化

上記データをグラフにて可視化します。

#売上の可視化
# グラフのタイトル
plt.title("Sales")
# グラフのx軸とy軸の名前設定
plt.xlabel("Week")
plt.ylabel("Quantity")

plt.plot(df3)
plt.grid()
plt.show()
週毎の売上数量のグラフ

4.パラメータの決定

PythonにはSARIMAモデルのパラメーターを自動で最も適切にしてくれる機能はありません。
そのため 情報量規準 (今回の場合は BIC(ベイズ情報量基準) )によってどの値が最も適切なのか調べるプログラムを書かなければなりません。こちらはAidemy提供のコードを使用します。

それにあたりパラメーター s(周期)に関しては事前に調べておく必要があります。
今回はデータが季節周期を持つと仮定してその周期を調べます。

# 季節調整を行い原系列をトレンド、季節変動、残差に分けて出力
fig = sm.tsa.seasonal_decompose(df3,period=12)
fig.plot()
plt.show()
季節調整の可視化

12か月で季節変動を繰り返していそうです。
早速、BIC(ベイズ情報量基準) )によってどの値が最も適切なのか調べます。

#52週分のデータ
df3_52 = df3[:52]

# パラメーターの最適化関数
#時系列データ:DATA, パラメータs(周期):sを入力すると、最も良いパラメーターとそのBICを出力します。
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)]

# 周期を埋めて最適なパラメーターを求める
selectparameter(df3_52,12)
パラメーター出力結果
# モデルの当てはめ
SARIMA_df3 = sm.tsa.statespace.SARIMAX(df3,order=(0, 1, 1),seasonal_order=(0, 1, 1, 12)).fit()

#BICを出力
print(SARIMA_df3.bic)
BIC出力結果

5.モデルの予測と可視化

最後に実際にSARIMAモデルを運用して2019年11月17日~2020年6月17日の売上数量予測をしていきます。
青線が実際の売上数量、赤線が予測数量となります。

# 予測
# predに予測期間での予測値を代入
pred = SARIMA_df3.predict("2019-11-17", "2020-06-20")

# グラフを可視化。予測値は赤色でプロット
plt.plot(df3)
plt.plot(pred, color="r")
plt.grid()
plt.show()
出力結果

結果

若干のズレはありますが結果と予測の部分も近しい結果になっているとおもいます。
今回はKaggleから持ってきたデータセットのデータ量が下記の通り少な目だったため季節性があるかの判断が難しく予測の向上が難しかったです。
・データの期間が1年程度分しかなかった事。
・上記に加え今回様々な商品をMIXで平均値で予測したため週毎の数量差が激しいこと。
分析の精度を上げるにはデータ量がある程度あるものを使用してテストしていくことが必要だと思いました。
また産休明けに実際のデータ等で試していきたいと思いました。

感想

この度、産休期間を利用して3か月コースにて学習しましたが学習範囲も広く、正直初歩的な部分しか習得できていないため、今後も時間を見つけて勉強を進め、仕事に利用できるようにしていきたいと思います。

今回は時系列解析を使用して売上予測を行いましたが別のモデル(Light GBM等)での検証も行い、精度が上がるか試していきたいと思います。
ありがとうございました。

この記事が気に入ったらサポートをしてみませんか?