Amazon Web Services ブログ
Amazon SageMaker Processingによるシフトスケジュール、輸送経路選択、資源配分などの数理最適化問題の解決
この記事では、 Amazon SageMaker Processing API を使用して数値最適化問題を解く方法について説明します。最適化とは、様々な制約条件のもと、ある関数の最小値(または最大値)を求めるプロセスです。このパターンは、作業スタッフのシフト作成や輸送ルート選定、在庫配分、形状や軌跡の最適化など、ビジネスにおける重要な問題の解決に役立ちます。このような問題を解くためには、商用もしくはオープンソースで提供される“ソルバー”というソフトウェアが利用されます。この記事では、無償で利用できる3つの一般的な Python のソルバーを SageMaker Processingで実行し、これらの最適化問題を解く方法を示します。
概要
SageMaker Processing により、データサイエンティストと ML エンジニアは、SageMaker 上で前処理や後処理、モデル評価などのAIや機械学習に必要なタスクを簡単に実行できるようになります。このSDKは、scikit-learn と Spark の組み込みコンテナを使用しますが、独自の Docker イメージを使用することもできます。これにより、SageMaker Processing に限らず、Amazon Elastic Container Service (Amazon ECS) や Amazon Elastic Kubernetes Service (Amazon EKS) のようなAWSコンテナサービス、あるいはオンプレミスであっても、どんなコードも実行できるという柔軟性が得られます。まず、一般的な最適化パッケージとソルバーを含んだ Docker イメージをビルドし、以下の3つの最適化例題を解きます。
- 物流ネットワークを通じて商品を出荷するコストを最小化する
- 病院における看護師のシフトをスケジューリングする
- アポロ11号の月着陸船を最小の燃料で着陸させる軌道を求める
それぞれの例題を、対応するソルバーを使用して解きます。おおまかには以下のステップに沿って各例題を解決します(こちらのノートブックを参照)。
- 最適化ソルバー(GLPK や CBC など)に対応する Python インターフェース(Pyomo や PuLP など)を含む Docker コンテナのイメージをビルドする。
- Amazon Elastic Container Registry (Amazon ECR) のリポジトリにビルドしたコンテナイメージをプッシュする。
- SageMaker Python SDKを使用して(ノートブックなどから)Amazon ECRの Docker イメージを指定し、実際の最適化問題のコードを含むPythonファイルを送信します。
- ノートブックまたは Amazon CloudWatch Logs でログを監視し、指定した Amazon Simple Storage Service(Amazon S3)の出力フォルダで結果を取得します。
以下にこの処理の全体像を図解します。
それでは始めましょう。
DockerコンテナのビルドとECRへのプッシュ
まずは以下のような Docker ファイルを作成します。
このコードでは、ソルバーにアクセスする Python インタフェースをインストールしています。ソルバーとは PuLP や Pyomo、Inspyred、OR-Tools、Scipy、DEAP のようなソフトウェアです。これらソルバーについてのより詳細な情報は、この記事の最後にある参考情報のセクションを参考にしてください。
以下のコードをノートブックから実行することで、コンテナイメージがビルドされ、Amazon ECR にプッシュされます。
上記のコードを実行した結果、以下のような出力が得られます(出力結果はサンプルであるため実行環境によって異なる点にご注意ください)。
SageMaker Python SDKによるジョブの実行
まず、以下のように SageMaker ProcessingScriptProcessor
を初期化します。
そして、スクリプトファイル(この記事では“preprocessing.py”というファイル名で作成します)を記述し、以下のように SageMaker の Processingジョブを実行します。
例題1: 最小のコストで商品を配送する流通ネットワークを選択する
オハイオ州に拠点を置く鋼鉄製造会社であるAmerican Steel社は、ヤングスタウンとピッツバーグにある2つの製鉄所で鋼鉄を生産しています。同社は地域倉庫と現場倉庫で構成される流通ネットワークを通じて、完成品の鋼鉄を小売り顧客に供給しています。
このネットワークでは、American Steel社の2つの製鉄所ヤングスタウン(ノード1)とピッツバーグ(ノード2)で製造された鋼鉄が、現場倉庫であるオールバニ、ヒューストン、テンペ、ゲーリー(ノード6、7、8、9)へ出荷されます。ただしその途中で、シンシナティ、カンザスシティ、シカゴ(ノード3、4、5)の3つの地域倉庫を経由します。なお、一部の現場倉庫へは製鉄所から直接製品が供給されることもあります。
以下の表は、それぞれの都市間で輸送可能な鋼鉄の最小および最大量と、1,000トンあたり1ヶ月の鋼鉄の輸送コストを示しています。例えば、ヤングスタウンからカンザスシティへの出荷は鉄道会社によって行われますが、最小出荷量が1,000トン/月の契約を結んでいます。ただし、鉄道会社の車両数の制限により1ヶ月に5,000トン以上を出荷することができません。
発地 | 着地 | コスト | 最小輸送量/月 | 最大輸送量/月 |
Youngstown | Albany | 500 | – | 1000 |
Youngstown | Cincinnati | 350 | – | 3000 |
Youngstown | Kansas City | 450 | 1000 | 5000 |
Youngstown | Chicago | 375 | – | 5000 |
Pittsburgh | Cincinnati | 350 | – | 2000 |
Pittsburgh | Kansas City | 450 | 2000 | 3000 |
Pittsburgh | Chicago | 400 | – | 4000 |
Pittsburgh | Gary | 450 | – | 2000 |
Cincinnati | Albany | 350 | 1000 | 5000 |
Cincinnati | Houston | 550 | – | 6000 |
Kansas City | Houston | 375 | – | 4000 |
Kansas City | Tempe | 650 | – | 4000 |
Chicago | Tempe | 600 | – | 2000 |
Chicago | Gary | 120 | – | 4000 |
一般的な転送問題と同様、American Steel社の目的はネットワークを通じて商品を出荷するコストを最小限にすることです。
本例題では、次の流入保存制約に従う必要があります。製品を製造する”製鉄所“には「供給」が定義されており、ここから流出する商品は「供給」量以下である必要があります。また、消費地に近い”現場倉庫“には「需要」が定義されており、「需要」量以上の商品が流入される必要があります。また、各ノードへの流入量は流出量以上である必要があります。
この問題は以下のようにコード化されます。
この例題を PuLP とそのデフォルトのソルバーである CBC を script_processor.run
で実行します。この最適化ジョブは以下のログを出力します。
例題2: 病院における看護師のシフトをスケジューリングする(ナーススケジューリング)
この例題では、4人の看護師の3日間の勤務スケジュールを作成します。ただし、勤務表の作成にあたっては以下の条件を満たす必要があります。
- 1日のスケジュールは 8 時間の 3 つのシフトで構成されます。
- 1日の中で 1 人の看護師が割り当てられるシフトは1つです。複数のシフトを勤務することはできません。
- 各看護師は 3 日間の期間中に少なくとも 2 つのシフトに割り当てられます。
このスケジューリング問題についてさらに詳しい情報はこちらをご参照ください。
この例題は以下のようにコード化されます。
この例題を OR-Tools とソルバーのCP-SATを使うよう、script_processor.run
で実行します。この最適化ジョブは以下のログを出力します。
例題3: アポロ11号の月着陸船を最小の燃料で着陸させる軌道を求める
この例題では、 Pyomo によるシンプルな宇宙ロケットのモデルを使用して、月面着陸のための制御ポリシーを計算します。
ここで使用しているパラメータは、1969年7月20日のアポロ11号月着陸船の月への降下時のものです。高度 h で垂直飛行中の質量 m のロケットの場合、運動量バランスにより次のモデルが得られます。
このモデルでは、 u は推進剤の質量流量、ve はロケットに対する排気の速度を表しています。モデリングと制御のこの最初の試みでは、燃料の燃焼によるロケットの質量の変化を無視します。
燃料消費量は以下の式で算出されます。
さらに以下で燃料消費量が最小となるような軌道を求めます。
この例題は以下のようにコード化されます。
この連続時間の軌道最適化問題を解決するため、 Pyomo と非線形最適化ソルバー Ipopt を使用します。 実行結果は以下のように ScriptProcessor.run
のログに出力されます。
まとめ
この記事では、SageMaker Processing を使用して数値最適化問題を解決するために、様々なフロントエンドツールやソルバーを試しました。さらに、Scipy.optimize やDEAP、Inspyred を使用して他の例題を試してみてください。自社におけるビジネス問題を SageMaker Processing を使用して解決する際には、次のセクションの参考文献や他の例題を参照してください。もし現在、機械学習プロジェクトで SageMaker API を使用している場合、最適化を実行するために SageMaker Processing を使用することは、シンプルな方式です。ただし、最適化問題の解決のためにこれらのオープンソースライブラリを実行するには、Lambda や Fargate などの他のAWSサービスも検討することをおすすめします。また、この記事で使用したオープンソースライブラリは最小限のサポートで提供される一方、CPLX や Gurobi などの商用ライブラリは常に高いパフォーマンスを追求しており、通常はプレミアムサポートも提供されています。
参考情報
- Training APIs: Processing
- https://pypi.org/project/PuLP/
- OR-Tools: Get Started Guides
- Pyomo Documentation 5.7.2
- inspyred: Recipes
- Optimization and root finding (scipy.optimize)
- DEAP documentation
- https://www.gurobi.com/
- CPLEX optimzer
- OR Tools code license
- PuLP code license
- Pyomo code license
著者について
Shreyas Subramanian は AI/ML specialist Solutions Architect です。機械学習を使ってAWSのお客様の課題解決に取り組んでいます。
この記事の翻訳はソリューションアーキテクトの横山誠が担当しました。原文はこちらです。