- HOME
- S4で始める強化学習(第9回)在庫管理問題で作ってみる(1/3)
2024年6月20日 17:01
本記事は当社が発行しているシミュレーションメールマガジンVol. 15の記事です。 シミュレーションメールマガジンの詳細・購読申込はこちらのサポートページから
- S4 で始める強化学習(第1回)離散イベントシミュレーションで使ってみる
- S4 で始める強化学習(第2回)離散イベントシミュレーションで作ってみる
- S4 で始める強化学習(第3回)離散イベントシミュレーションで理解を深める
- S4 で始める強化学習(第4回)エージェントシミュレーションで使ってみる
- S4 で始める強化学習(第5回)エージェントシミュレーションで作ってみる(1/2)
- S4 で始める強化学習(第6回)エージェントシミュレーションで作ってみる(2/2)
- S4 で始める強化学習(第7回)エージェントシミュレーションで理解を深める
- S4 で始める強化学習(第8回)在庫管理問題で使ってみる
- S4 で始める強化学習(第9回)在庫管理問題で作ってみる(1/3)
- S4 で始める強化学習(第10回)在庫管理問題で作ってみる(2/3)
はじめに
S4 で強化学習を使ったシミュレーションモデルを作成してみようという講座の9回目の記事になります。
今回からは第8回でご紹介した在庫管理問題のシミュレーションモデルの作成について、3回に分けてご紹介していきます。最初の2回では在庫管理問題のモデルの組み立て、最後の1回で強化学習モデルの組み込みを行う予定です。 前回の記事をご覧になっていない方はS4 で始める強化学習(第8回)在庫管理問題で使ってみるをご覧ください。
在庫管理問題モデルの概要
今回の在庫管理モデルは第1回から第3回でご紹介したシミュレーションと同じように離散イベントシミュレーションとして実現します。 モデルの編集画面はこのような形になっています。
大きく分けてフローが2つあることが分かるかと思います。上側はお客からの注文を受け在庫を消費する在庫消費フロー 下側は在庫の状況をチェックして上流に在庫補充の注文をかける在庫補充フローになります。 在庫補充数を強化学習を用いて決定するため、在庫補充フローには強化学習に関する部品が組み込まれています。
また、強化学習の観測値としては在庫の量と発注済みの到着待ち製品数、即時報酬としては前日の売上個数と在庫の量を用いるため、それらの量を観測できるようにしています。強化学習が進んでいることを確認するために、累積の利益と顧客損失についても確認できるようにしています。
実装の方針
今回のモデルの実装は次のように4段階に分けて行いました。
- 在庫消費フローの実装
- 在庫補充フローの実装
- 強化学習モデルの組み込み
- 強化学習結果の可視化
S4 で始める強化学習(第5回)エージェントシミュレーションで作ってみる(1/2)の実装の方針と同じく、強化学習モデルを組み込む前に動くものを完成させていきます。大きいモデルを動かす場合は、できるだけ小さい設定で動くことを確認しながら、組み合わせていったり拡張していくことをお勧めいたします。
分量が多いため、今回はstep1の実装のみを行います。step1まで実装を行ったs4プロジェクトはこちらからダウンロードいただけます。
step1:在庫消費フローの実装
在庫消費フローで実現すること
在庫消費フローで実現すべきことを前回の問題設定をもとに改めて整理しておきましょう。
- 小売店には毎日確率的に客から注文が入る
- 小売店の在庫が足りなくなるとただちに失注し、顧客損失となる
- その日の売り上げを確認できるように記録を取る
- 累積顧客損失の値を更新し記録する
- 累積利益の値を更新し記録する
最後の「累積利益」については、在庫補充フローでの発注も影響しますので、別のフローにまたがって値を更新できるような仕組みを作ります。初めに利益計算に関わらないフローのみを実装し、最後に利益計算・記録を実装することにします。
フローの組み立て
新規プロジェクトの作成を行い、まずは必要なアイテムや資源を配置していきます。
編集後のアイテム/資源名 | デフォルトアイテム/資源名 | タブ | 説明 |
---|---|---|---|
需要 | アイテム | アイテム | お客から入る需要を表す。このフローを流れていくモノ。 |
在庫 | ストア | 資源 | 在庫を表す。製品を蓄える機能を持つ。 容量:制限なし, 初期状態の複製数15に設定しておく。 |
売り上げ | ストア | 資源 | その日の売り上げた製品個数を覚えておくため、売り上げ直後の1日だけこのストアに販売個数を保存する。 容量:制限なしに設定しておく。 |
以上の3つが今回のフローの登場人物になります。
次に「部品」タブの基本部品を使ってフローを組み立てます。以下の図を参考に最終的なフローを意識しながら部品を配置していきます。
大まかな流れは部品名から想像いただけると思いますが、このフローでは毎日需要が確率的に発生し、その需要に合わせて在庫を消費し売り上げとして記録します。在庫が足りない場合は即時に下側の分岐に流れ、顧客損失としてカウントされるという仕組みになっています。
それぞれの部品の名前と編集後の名前、設定についての一覧は以下のようになります。
編集後の部品名 | デフォルト部品名 | 設定箇所 |
---|---|---|
需要発生 | 生成 | フローアイテム名:Item(需要) 1回の生成数: 最小3, 最大(未満)6の一様分布 |
分割[1] | 分割 | |
ストアから取得 | 在庫消費 | ストア:rStore(在庫) 出力ポートtimeoutを新たに追加[2] 最大待ち時間:最大待ち時間0, タイムアウト時出力ポートをtimeoutに設定 |
売り上げ一時記録 | ストアへ追加 | ストア:rStore2(売り上げ) 追加個数:固定, 整数, 1 |
遅延 | 遅延 | 出力前の待ち時間:固定, 実数, 1 並列処理:並列数Inf[3] |
売り上げ一時記録2 | ストアから取得 | ストア:rStore2(売り上げ) 取得個数:整数, 1 |
累積顧客損失 | 記録 | モニター種類:時系列モニター 列名:累積顧客損失 列の型:整数 記録方法:累積カウント |
終端 | 終端 |
- 「需要発生」部品では、一度に複数個(今回は3-5個)のアイテムを生成しています。複数個のアイテムを一度に生成すると、フロー上にはアイテムをまとめたアイテムリストというものが流れることになります。今回は、1個1個の需要(=お客からの注文)を1つずつ処理したいため、「分割」という部品を挟んでいます。
- 出力ポートは部品編集画面の共通設定タブから「出力」の隣の+ボタンを押すことで新規追加できます。
- 「遅延」部品では並列処理を指定する必要があります。逐次処理を指定した場合、遅延を1つずつ処理するため、今回の意図通り動作しません。
記録の確認
部品の配置が完了したら、早速モデルを実行して、正しく動いているかどうか確認してみましょう。今回は在庫の消費のみを考えているため、最初に補充してある15個の在庫がなくなるとその後は売り上げが増えず、顧客損失だけが増えるはずです。
実行後の出力フォルダに「在庫」「売り上げ」「累積顧客損失-記録」というデータが作成されます。前2つはストア部品の機能を使った記録、最後の1つは記録部品によって作成されたものです。「パラメータを編集する」から乱数の種を0に設定すると以下と同様の結果が得られるはずです。
まず、在庫量と売り上げの個数の記録が整合することを確認してみましょう。0日目(時刻0を指します)の売り上げは、「売り上げ」のデータのバッファ列の値に相当しますが、これは4が記録されています。一方で、0日目の在庫のバッファは11となっています。在庫の初期化時はバッファが15であるため、たしかに売り上げた分の製品が在庫から引かれていることが分かります。この後も同様に、売り上げの分だけ在庫が減っていることを確認できます。
さらに、3日目には在庫が0となることが見て取れます。この日の売り上げは2となっており、最初の2つの注文以降は在庫が足りずに顧客損失となっていると考えられます。実際、累積顧客損失のデータを確認すると、3日目に初めての顧客損失が発生し、その後はひたすら顧客損失が増えていく様子を確認できます。
累積利益記録
利益計算には「売り上げた製品数」、「在庫管理費」、「発注数」が関係します。今回は売上製品数のみを記録すればよいですが、今後step2で実装する在庫補充フローでも利益の値を更新する必要があります。 このような場合には、例えばパラメータを使って利益を記録するような方法があります。
S4のパラメータ編集画面のパラメータタブから以下のようなパラメータを設定しておきます。
- profit: 累積利益を表す。値(初期値)を0とする。
- price: 売り上げ単価を表す。値を4と設定しておく。
まず、累積利益を表すprofitの値を売り上げがあるたびに更新させてみます。分岐後の「売り上げ一時記録」の直後に「設定」部品を追加します。名前は「利益更新(売り上げ)」と編集します。
設定部品ではアイテム属性やパラメータの更新などができます。今回はすでに設定してあるパラメータprofitの値をparam.profit + param.priceという値で更新します。これにより、この部品をアイテムが通過する、つまり一つ製品が売れるたび、profitの値にpriceの値が加えられることになります。
更新ができたことを確認するためにも、このprofitの値を確認するための記録部品を配置してみましょう。フローのどこに挟んでも問題ありませんが、分割部品の後ろに配置すると無駄に何回も同じ時間の記録を取ることになるため、分割部品の前に配置することにします。記録部品のモニター種類は時系列モニター、記録内容の列名は「累積利益」とし、式 param.profit を記録します。
記録部品の配置後、再びシミュレーションを回して記録内容を確認すると、累積利益は4日目頭時点で60となり、そこで頭打ちになります。もともと在庫は15個あり、1製品の売り上げ単価は4としていたので確かに在庫を売り切った利益になっています。
おわりに
今回はまだあまり面白いグラフになりませんが、累積顧客損失や累積利益については強化学習時にグラフを参照すると状況を把握しやすいです。グラフ部品はこの時点で配置可能なため、この時点で組み込まれるとよいのではないかと思います。
次回までは強化学習には直接関係しない部分のモデルの解説を行う予定です。今回のように離散イベントシミュレーションモデルのよくある話題も盛り込んでいきますので、気楽に目を通していただけたら幸いです。
http://www.msi.co.jp NTTデータ数理システムができること