【SCM分析7】需要予測による在庫削減効果を適正在庫シミュレーション

2023年10月16日

本サイトでは安全在庫理論を使った適正在庫シミュレーションの作り方を、Excel VBA版とPython版で公開しています。

【無料サンプル付き】適正在庫シミュレーションをエクセルで作る方法

【Pythonで実装する】適正在庫シミュレーションソフトを作ってみた。

 

肝となるのは安全在庫需要予測在庫で、これらを足した在庫補充目標量になるように発注量を決めるという考え方で日々の在庫推移をシミュレーションします。

このうち安全在庫は出荷実績のばらつきを標準偏差で表し、それに許容欠品率に対応した安全係数を掛けることにより求めます。

需要予測在庫は出荷実績から1日当たりの平均出荷量を求め、それにリードタイム+発注サイクルを掛けて求めます。

 

しかし需要予測在庫はもっと精度良く求める方法があります。

それは【SCM分析6】AICを指標とするSARIMAモデルの自動構築で出荷数量を需要予測でやったような需要予測を使う方法です。

需要予測在庫とは発注してから納品されるまでの期間の予測出荷量を賄うための在庫なので、その期間の需要予測値を使えばいいのです。

本記事では従来の方法(需要予測を行わない方法)に比べて、需要予測を行うことでどのくらい在庫削減効果があるかをシミュレーションしてみました。

 

【ゆっくり解説】Youtubeはじめました!

出荷実績データの読み込み

前回の記事と同じ出荷実績データを使います。

半年分ありますので、最初の5ヶ月分を学習データ、残りの1ヶ月分をテストデータとします。

テストデータの行数をシミュレーション日数、列数をシミュレーションアイテム数として取得しておきます。

from sklearn.model_selection import train_test_split
learn_df, test_df = train_test_split(data_df, test_size=31, shuffle=False)
learn_data = learn_df.to_numpy()
test_data = test_df.to_numpy()
rows, columns = test_data.shape # テストデータの行数と列数を取得
days = rows # 行数はシミュレーション日数
items = columns - 1 # 列数-1はSKU数(最初の列は日付であるため)
days, items
…
(31, 1)

 

需要予測を行わない方法でシミュレーション

あとは行列演算を使った複数SKUの適正在庫シミュレーションをPythonで実装するで作ったコードを使ってシミュレーションが実行できます。

結果は次のようになりました。

またこの期間の平均在庫数は次のようになりました。

current_stock_list.mean()
…
3474.456395707775

 

需要予測を行う方法でシミュレーション

変更点

需要予測結果を適正在庫シミュレーションで使えるようにするための変更点は次の通りです。

 

実績値―需要予測値)の標準偏差を使う

安全在庫を求めるには標準偏差が必要です。

需要予測を行わない場合は過去の出荷実績データの標準偏差を使いましたが、需要予測を行う場合は(実績値―需要予測値)の標準偏差を使います。

需要予測の誤差分だけ安全在庫を持つという考え方です。

 

まずは5ヶ月分のデータからSARIMAモデルを使って需要予測値を求めます。

best_model = SARIMAX(df_train,
                    order = (0, 1, 2),
                    seasonal_order = (0, 2, 2, 7))
best_result = best_model.fit()
fitting = best_result.get_prediction() # 学習データ期間の予測値をget
fitting_mean = fitting.predicted_mean # 予測値の期待値をget
forecast = best_result.get_forecast(len(df_test)) # テストデータ期間の予測値をget
forecast_mean = forecast.predicted_mean # 予測値の期待値をget

次に、学習データ期間における実績値と需要予測値の差異を求め、その不偏標準偏差を計算します。

diff = df_train.S00239 - fitting_mean
diff.std()
…
336.90787435566784

これに安全係数を掛けた値が安全在庫になるので、小さければ小さいほど在庫は減ることになります。

ちなみに需要予測を行わない場合におけるこの不偏標準偏差の値は374でした。

需要予測を行うことにより、少しだけ小さくなったことがわかります。

 

出荷実績平均の代わりに需要予測値を使う

需要予測を行わない場合は5ヶ月分の出荷実績値の平均を取り、それに(リードタイム+発注サイクル)を掛けて需要予測在庫を求めました。

従って、シミュレーション期間の1ヶ月間に渡って1つの需要予測在庫を使います。

ところが需要予測を行う場合には、日々この値が変わります。

需要予測値は日々変わるからです。

 

例えば今日が3日で、リードタイム+発注サイクルが5日だったとすると、4~8日の間の需要予測値の合計が3日時点での需要予測在庫になります。

このように日々の需要予測値が必要になりますので、まずは1ヶ月間の毎日の需要予測値をリストに格納しておきます。

av_list = [] # 各SKUの需要データの需要予測値を入れる空のベクトル
for i in range(1, items+1):
    for j in range(0,len(forecast_mean)):
        av = forecast_mean[j]
        av_list.append(av)

これでav_listに31個の需要予測値が入りました。

 

需要予測期間を求める

需要予測期間はリードタイム+発注サイクルになります。

リードタイムも発注サイクルも毎日一定で、それぞれld_listとod_listに入っていますので、これらを足してlagという変数に入れておきます。

# 初期設定
ld_list = np.full(items, 3) # すべてのSKUのリードタイム=3日
oc_list = np.full(items, 2) # すべてのSKUの発注サイクル=2日
lag = ld_list[0] + oc_list[0] # 需要予測期間=リードタイム+発注サイクル

 

需要予測値から需要予測在庫を求める

先述したように毎日需要予測期間先までの需要予測値を足し合わせた値を需要予測在庫として計算しますが、これには場合分けが必要です。

シミューレーション期間は31日間です。

需要予測期間が5日間だった場合、26日目までは5日先までの需要予測値がありますが、それ以降は需要予測値が足りないからです。

そこで27日目以降は、1週間前の需要予測値を使いました。

1週間の周期変動があるためです。

# 需要予測在庫の計算
cycle_stock_by_item = []
for i in range(1, items+1):
    for j in range(0, len(forecast_mean) - lag): # 需要予測期間がテストデータに含まれる場合
        cycle_stock = 0
        for k in range(lag):
            cycle_stock = av_list[j + k] + cycle_stock # 需要予測期間の予測数量
        cycle_stock_by_item.append(cycle_stock)
    for j in range(len(forecast_mean) - lag, len(forecast_mean)): # 需要予測期間がテストデータからはみ出す場合
        cycle_stock = cycle_stock_by_item[j - 7] # 7日前の需要予測数量を使う
        cycle_stock_by_item.append(cycle_stock)

これでcycle_stock_by_itemに31個の需要予測在庫がリストとして格納されました。

 

シミュレーション結果

その他の部分は行列演算を使った複数SKUの適正在庫シミュレーションをPythonで実装するで作ったコードと同じです。

シミュレーション結果は次のようになりました。

そして平均在庫数は次のようになりました。

current_stock_list.mean()
…
2370.863960735379

需要予測を行わない場合は3,474なので、32%の在庫削減になりました。

需要予測のある/なしでシミュレーション結果を並べて表示すると次のようになります。

安全在庫はさほど変わらないものの、需要予測値を使うことによって無駄な需要予測在庫を持つ必要がなくなった効果が大きいといえます。

 

まとめ

需要予測を行うことで適正在庫が減ることがシミュレーションで確認できました。

これには2つの要因があると考えられます。

 

安全在庫の低減

需要予測を行わない場合・・・過去実績の標準偏差✕安全係数

需要予測を行う場合・・・(過去実績―需要予測値)の標準偏差✕安全係数

後者の方が一般的に小さいため安全在庫が低減される。

 

需要予測在庫の低減

需要予測を行わない場合・・・過去実績の平均✕(リードタイム+発注サイクル)

需要予測を行う場合・・・(リードタイム+発注サイクル)期間の需要予測値

前者の方が多過ぎたり少な過ぎになる可能性が高いことは明らか。

 

今はPythonのライブラリーを使えば簡単に需要予測ができる時代になっています。

【Pythonで需要予測②】SARIMAモデルの自動構築で出荷数量を予測してみた

またその需要予測値を使って適正発注量を計算することもPythonで簡単にできます。

一昔前までは高価な専用のソフトに投資しないとできなかったことが、Pythonで自作できる時代になったのです。