PythonとGridDBを使った売上予測

売上予測とは、過去のデータに基づいて、ある期間の将来の売上を予測する処理です。予測は、多くの企業の収益性を左右する貴重なツールであるため、習得すべき重要なスキルです。予測は、企業の計画や方向性を導くのに役立ちます。自己回帰統合移動平均(ARIMA)、季節自己回帰統合移動平均(SARIMA)、ベクトル数(VAR)など、世の中にはいくつかの方法が存在します。今回は、Kerasを使ってLSTM(Long Short-term Memory)モデルを実装してみます。LSTMは、フィードバックループに頑健なニューラルネットワークの一種です。

リカレントニューラルネットワークの主な問題点として、時間の経過とともに、隠れ状態に保持されている情報が過負荷になることが挙げられます。LSTMは、ステップからステップへ持続する追加の隠れ状態を維持することで、オーバーロードを軽減します。LSTMの詳細はこちらを参照してください。GridDBはスケーラブルで信頼性が高いので、ニューラルネットワークの学習や推論に最適なデータベースとして利用できます。GridDBのインストールは簡単で、こちらに詳しい説明があります。Python-GridDBクライアントを確認するには、こちらのビデオを参照してください。

LSTM

セットアップ

まずはGridDBをセットアップしましょう

Ubuntu 20.04でGridDB Python Clientのセットアップを行います。

  • GridDBのインストール

こちらからdebをダウンロードし、インストールします。

  • C言語のクライアントをインストールする

こちらからUbuntuをダウンロードし、インストールします。

  • 必要機材のインストール

1) Swig コンソール


wget https://github.com/swig/swig/archive/refs/tags/v4.0.2.tar.gz
tar xvfz v4.0.2.tar.gz
cd swig-4.0.2
./autogen.sh
./configure make

2) pythonクライアントのインストール


wget \ 
https://github.com/griddb/python_client/archive/refs/tags/0.8.4.zip 
unzip . 0.8.4.zip 

対応するpythonのバージョンに対応するpython-devがインストールされていることを確認してください。この記事では、python 3.8を使用します。

3) 正しい場所を指定する必要があります。


export CPATH=$CPATH:<python header file directory path> 
export LIBRARY_PATH=$LIBRARY_PATH:<c client library file directory path> 
</c></python>

また、こちらのように、DockerでGridDBを利用することも可能です。

Python ライブラリ

次に、Pythonのライブラリをインストールします。plotly、numpy、keras、tensorflow、pandasのインストールは、pip installで簡単にできます。

pip install keras 
pip install numpy 
pip install tensorflow 
pip install plotly 
pip install pandas 

予測

ステップ1:データセットのダウンロード

このKaggleプロジェクトからデータをダウンロードすることができます。このデータセットには、Order Info, Sales, Customer, Shippingなどが含まれており、Segmentation, customer analytics, clusteringなどに利用することができます。今回は売上予測に使うので、売上と注文の日付のみを対象としています。月次の売上を予測します。

ステップ2: ライブラリのインポート


import numpy as np 
import pandas as pd 
import plotly.offline as pyoff 
import plotly.graph_objs as go 

ステップ3:データの読み込みと処理

データの読み込み

data=pd.read_csv('/content/sales_data_sample.csv', encoding='cp1252') 

上記で使用したエンコードオプションに注意してください。

また、GridDBを使用してこのデータフレームを取得することも可能です。

特徴量のエンコーディング

まず、月単位でデータを照合する。各日付を月初にseするだけです。そして、その月の平均売上を算出します。すべての日に売上があるわけではないことに注意してください。

data['ORDERDATE'] = pd.to_datetime(data['ORDERDATE']) 
data['ORDERDATE'] = data['ORDERDATE'].dt.year.astype('str') + '-' + data['ORDERDATE'].dt.month.astype('str') + '-01' 
data['ORDERDATE'] = pd.to_datetime(data['ORDERDATE']) 
data = data.groupby('ORDERDATE').SALES.mean().reset_index() 

次に、売上高をプロットしてみます。データには、特に11月頃に季節性があることがわかります。

plot_data = [ 
    go.Scatter( 
        x=data['ORDERDATE'], 
        y=data['SALES'], 
    ) 
] 
plot_layout = go.Layout( 
        title='Monthly Sales' 
    ) 
fig = go.Figure(data=plot_data, layout=plot_layout) 
pyoff.iplot(fig) 

次に、売上高の差の列を追加し、ヌルを削除します。ヌルは最後の値だけで、その差は作れないのでヌルになります。ラグを設定することで、モデルは直近の売上だけでなく、それ以前の売上からも学習することができます。

df_supervised = data.copy() 
df_supervised['prev_sales'] = df_supervised['SALES'].shift(1) 
df_supervised['diff'] = (df_supervised['SALES'] - df_supervised['prev_sales'])
df_supervised = df_supervised.drop(['prev_sales'],axis=1) 
for inc in range(1,3): 
    field_name = 'lag_' + str(inc) 
    df_supervised[field_name] = df_supervised['diff'].shift(inc) 
#drop null values 
df_supervised = df_supervised.dropna().reset_index(drop=True) 

データを検証用と訓練用に分割する

次に、データをテストとトレーニングに分けます。テストには、過去6ヶ月のデータを使用しました。


from sklearn.preprocessing import MinMaxScaler 
df_model = df_supervised.drop(['SALES','ORDERDATE'],axis=1) 
#split train and test set 
train_set, test_set = df_model[0:-6].values, df_model[-6:].values 

また、データのスケーリングも行います。テストセットとトレーニングセットを別々にスケーリングすることに注意してください。これは、訓練セットとテストセットが独立したままであるようにするためです。

#apply Min Max Scaler 
scaler = MinMaxScaler(feature_range=(-1, 1)) 
scaler = scaler.fit(train_set) 
# reshape training set 
train_set = train_set.reshape(train_set.shape[0], train_set.shape[1]) 
train_set_scaled = scaler.transform(train_set) 
# reshape test set 
test_set = test_set.reshape(test_set.shape[0], test_set.shape[1]) 
test_set_scaled = scaler.transform(test_set) 
X_train, y_train = train_set_scaled[:, 1:], train_set_scaled[:, 0:1] 
X_train = X_train.reshape(X_train.shape[0], 1, X_train.shape[1]) 
X_test, y_test = test_set_scaled[:, 1:], test_set_scaled[:, 0:1] 
X_test = X_test.reshape(X_test.shape[0], 1, X_test.shape[1]) 

ステップ4: 予測

次に、予測処理を開始します。

初期化

まずKerasでLSTMモデルを作成します。そのためにLSTMレイヤーを使用します。

# define the keras model 
from keras.models import Sequential 
from keras.layers import LSTM, Dense 
model = Sequential() 
model.add(LSTM(4, batch_input_shape=(1, X_train.shape[1], X_train.shape[2]), stateful=True)) 
model.add(Dense(1)) 

トレーニング

次に、モデルをコンパイルします。損失としてmean_squared_errorを使用し、精度で評価します。

model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy']) 

次に、100エポック分のモデルの学習を行います。

history=model.fit(X_train, y_train, epochs=100, batch_size=1, verbose=1, shuffle=False) 
Epoch 72/100 

20/20 [==============================] - 0s 2ms/step - loss: 0.1302 - accuracy: 0.0000e+00 
Epoch 73/100 
20/20 [==============================] - 0s 2ms/step - loss: 0.1287 - accuracy: 0.0000e+00 
Epoch 74/100 
20/20 [==============================] - 0s 2ms/step - loss: 0.1272 - accuracy: 0.0000e+00 
Epoch 75/100 
20/20 [==============================] - 0s 2ms/step - loss: 0.1258 - accuracy: 0.0000e+00 
Epoch 76/100 
20/20 [==============================] - 0s 2ms/step - loss: 0.1244 - accuracy: 0.0000e+00 

評価と予測

最後に、テストセットを評価し、予測値を再スケールして、グランドトゥルースとともにプロットします。

y_pred = model.predict(X_test,batch_size=1) 
y_pred = y_pred.reshape(y_pred.shape[0], 1, y_pred.shape[1]) 

pred_test_set = [] 
for index in range(0,len(y_pred)): 
    pred_test_set.append(np.concatenate([y_pred[index],X_test[index]],axis=1)) 

pred_test_set = np.array(pred_test_set) 
pred_test_set = pred_test_set.reshape(pred_test_set.shape[0], pred_test_set.shape[2]) 
pred_test_set_inverted = scaler.inverse_transform(pred_test_set) 

result_list = [] 
sales_dates = list(data[-7:].ORDERDATE) 
act_sales = list(data[-7:].SALES) 
for index in range(0,len(pred_test_set_inverted)): 
    result_dict = {} 
    result_dict['pred_value'] = int(pred_test_set_inverted[index][0] + act_sales[index]) 
    result_dict['ORDERDATE'] = sales_dates[index] 
    result_list.append(result_dict) 

df_result = pd.DataFrame(result_list) 
#merge with actual sales dataframe 
df_sales_pred = pd.merge(data,df_result,on='ORDERDATE',how='left') 
#plot actual and predicted 
plot_data = [ 
    go.Scatter( 
        x=df_sales_pred['ORDERDATE'], 
        y=df_sales_pred['SALES'], 
        name='actual' 
    ), 
        go.Scatter( 
        x=df_sales_pred['ORDERDATE'], 
        y=df_sales_pred['pred_value'], 
        name='predicted' 
    ) 
] 
plot_layout = go.Layout( 
        title='Sales Prediction' 
    ) 
fig = go.Figure(data=plot_data, layout=plot_layout) 
pyoff.iplot(fig) 

予測値は、数100の誤差で、近いことがわかります。これは、非常に単純なモデルで数分のうちに十分に近い予測ができる、予測の力を示しています。

結論

この記事では、Keras、python、gridDBを使用してLSTM予測モデルを学習する方法を学びました。

ブログの内容について疑問や質問がある場合は Q&A サイトである Stack Overflow に質問を投稿しましょう。 GridDB 開発者やエンジニアから速やかな回答が得られるようにするためにも "griddb" タグをつけることをお忘れなく。 https://stackoverflow.com/questions/ask?tags=griddb

Leave a Reply

Your email address will not be published. Required fields are marked *