00:28 導入
00:43 ロバート・A・ハインライン
03:03 これまでの経緯
06:52 パラダイムの選択肢
08:20 静的解析
18:26 配列プログラミング
28:08 ハードウェアの相溶性
35:38 確率的プログラミング
40:53 微分可能プログラミング
55:12 コードとデータのバージョン管理
01:00:01 セキュアプログラミング
01:05:37 結論として、サプライチェーンでもツールは重要
01:06:40 次回の講義と聴衆からの質問
説明
主流の サプライチェーン理論 が大企業で広く受け入れられるのに苦戦する一方で、一つのツール、すなわちMicrosoft Excelは、運用面で非常に大きな成功を収めています。主流サプライチェーン理論の 数値レシピ を スプレッドシート を通じて再実装するのは容易ですが、理論が知られているにもかかわらず実際にはそうならなかったのです。私たちは、サプライチェーンの結果を提供する上で優れていると証明された プログラミングパラダイム を採用することで、スプレッドシートが勝利したことを示します.
全文記録
皆さん、こんにちは。このサプライチェーン講義シリーズへようこそ。私はジョアネス・ヴェルモレルです。本日は第4講義「サプライチェーンのためのプログラミングパラダイム」をご紹介いたします.
私に「ヴェルモレルさん、サプライチェーンの知識において最も興味深い分野は何だと思いますか?」と尋ねられると、通常、私の最も上位の回答はプログラミングパラダイムです。そして、そう頻繁ではないものの、十分に頻繁に、話をしている相手からは「プログラミングパラダイムですか、ヴェルモレルさん?一体何の話をしているのですか?それがどのようにして現状の課題に関連するのですか?」という反応が返ってきます。そして、そのような反応が起こるたびに、科学フィクション作家の学長と称されるロバート・A・ハインラインの驚くべき名言を思い出すのです.
ハインラインは、有能な人物についての素晴らしい言葉を残しており、これは特にサプライチェーンにおいて手に負えない問題に直面している我々にとって、各分野の能力の重要性を強調しています。これらの問題は人生そのものと同じくらい困難であり、プログラミングパラダイムの考え方を探求することは、あなたのサプライチェーンに大きな価値をもたらすと信じています.
これまでの第1講義では、サプライチェーンの問題がいかに困難であるかを見てきました。最適な解決策を語る者は本質を捉えていません。最適性に近いものは存在しません。第2講義では、サプライチェーン管理における卓越性を実現するための5つの重要な要件を備えたビジョンである 量的サプライチェーン を概説しました。これらの要件はそれだけでは十分ではありませんが、偉大さを目指すならば無視できないものです.
第3講義では、サプライチェーン最適化の文脈におけるソフトウェア製品の提供について議論しました。サプライチェーン最適化においては、資本主義的な手法で適切に対処すべきソフトウェア製品が必要だと主張しましたが、そのような製品は市場には存在しません。多様性が非常に豊かで、現行の技術をはるかに超えた課題に直面しているからです。したがって、必然的に、対象企業またはサプライチェーン向けに完全にオーダーメイドのものになるでしょう。もしそのソフトウェア製品が、該当企業や対象サプライチェーン向けにオーダーメイドであるならば、その製品を実際に提供するための適切なツールは何かという疑問が生じます。これが本日のテーマ、すなわち適切なツールは正しいプログラミングパラダイムから始まるということなのです。なぜなら、その製品をどうにかしてプログラミングしなければならないからです.
これまで、我々は問題の最適化側に対処するためのプログラム能力が必要であると論じてきましたが、それは管理側と混同してはいけません。前回の講義で見たように、Microsoft Excelはこれまでのところ勝者でした。小規模な企業から大企業に至るまで、どこでも使われています。何百万ドルもの投資をして超高度なシステムを構築している企業でも、Excelは依然として支配的で、その理由は適切なプログラミング特性を備えているからです。Excelは非常に表現力があり、柔軟で、アクセスしやすく、保守面にも優れています。しかし、Excelが最終目的ではありません。私たちは、もっと多くのことができると固く信じていますが、そのためには適切なツール、思考法、洞察、そしてプログラミングパラダイムが必要です.
プログラミングパラダイムは聴衆にとって非常に抽象的に感じられるかもしれませんが、実は過去50年にわたって集中的に研究されてきた学問分野です。この分野では膨大な量の研究が行われ、多くの高品質な成果が積み重ねられています。そこで本日は、Lokadが採用した7つのパラダイムのシリーズを紹介します。これらのアイデアは私たちが発明したものではなく、先人たちから受け継いだものです。これらすべてのパラダイムはLokadのソフトウェア製品に実装され、Lokadを運用してほぼ10年、これらのパラダイムを活用してきた結果、運用上の成功に絶対不可欠であったと信じています.
このリストを静的解析で進めていきましょう。ここでの問題は複雑性です。サプライチェーンにおける複雑性にどう対処するか?数百のテーブル、それぞれに数十のフィールドを持つエンタープライズシステムに直面するでしょう。もし単純な問題、例えば 在庫補充 を 倉庫 で扱う場合、考慮すべき点が非常に多く存在します。 最小発注量 (MOQ)、価格の分岐、需要予測、リードタイムの予測、さらには各種返品が考えられます。棚スペースの制限、受け入れ能力の限界、そして賞味期限によって一部のバッチが無効になるなど、多くの要素を考慮しなければなりません。サプライチェーンにおいて「速く動いて壊す」という考え方は適切ではありません。もし誤って不要な商品を100万ドル分注文してしまったら、それは非常に高額なミスとなります。ソフトウェアがサプライチェーンを駆動し、日常的な意思決定を行い、万一バグが発生すれば数百万ドルの損失に直結します。設計段階で極めて高い正確性を持たせる必要があり、本番環境でバグを発見したくはありません。これは、クラッシュしても大したことにならない一般的なソフトウェアとは全く異なります.
サプライチェーン最適化は、通常の問題とは一線を画します。もし一度、サプライヤーに対して大量の誤った注文を出してしまった場合、たった1週間後に電話で「すみません、注文は取り消してください」と言えるわけではありません。そのようなミスは多大な費用を伴います。静的解析とは、プログラムを実行せずに解析することを意味します。つまり、ステートメントやキーワードで記述されたプログラムについて、実行せずともそのプログラムに生産に悪影響を及ぼす問題があるかどうかを判断するという考え方です。答えはイエスです。これらの技術は存在し、実装されており、極めて価値があります.
例えば、画面上にEnvisionのスクリーンショットが表示されています。EnvisionはLokadによってほぼ10年間開発され、サプライチェーンの 予測最適化 に特化したドメイン固有のプログラミング言語です。ここに表示されているのは、オンラインでコードを編集できるWebアプリのEnvisionコードエディタのスクリーンショットです。その構文はPythonの影響を強く受けています。このたった4行のスクリーンショットで、もし倉庫での在庫補充のための大規模なロジックを書き、価格の分岐といった経済変数を論理的に導入した場合、これらの価格分岐が返される補充数量とは全く関係がないことが分かる、という考えを示しています。ここには明確な問題があり、重要な変数である価格分岐を導入しているにもかかわらず、その価格分岐が論理的にプログラムの出力に一切影響を与えていないのです。従って、これは静的解析によって検出可能な問題です。もしコード内で出力に全く影響しない変数を導入するのであれば、それは全く意味をなさないからです。この場合、死んだコードとしてプログラムはコンパイルされるべきではない(複雑性を軽減し、偶発的な複雑さを積み重ねないためにこの死んだコードは削除されるべきです)、もしくは、本来計算に組み込むべき重要な経済変数が存在したが、何らかの注意不足等でそれが落とされてしまったというどちらかの選択肢になります.
静的解析は、設計段階でどれだけの正確性を達成できるかに不可欠です。コードを書いている段階、データに触れる前に問題を解決できるため、もし実行時に問題が発生するとしても、それは夜間バッチ処理中の倉庫在庫補充の際など、誰も監視していない時間に起こる可能性があるからです。プログラムは、人が直接監視していない奇妙な時間に動作する可能性があるため、誰もいないときにクラッシュしてしまうのは避けるべきです。クラッシュは、実際に人々がコードを書いている時間帯に発生すべきです.
静的解析には多くの目的があります。例えば、LokadではダッシュボードのWYSIWYG編集に静的解析を利用しています。WYSIWYGとは「見たままが得られる」という意味です。ラインチャート、バーチャート、テーブル、色彩、様々なスタイリング効果を用いて報告用のダッシュボードを構築するとき、コードを直接いじるのではなく、視覚的にそれを作成できるようにしたいのです。実装した全ての設定はコードに再注入され、これが静的解析を通じて行われます.
また、Lokadでは、我々が開発しているEnvisionというプログラミング言語の設計上のミスに対処する必要がありました。ほぼ10年前の初日から、ミスは避けられないと分かっていました。初日から完璧なビジョンを持つことは不可能です。問題は、言語自体の設計ミスをいかにしてできるだけ容易に修正できるかという点にありました。ここで、Pythonは私にとって警鐘となりました.
Pythonは新しい言語ではなく、1991年に初めてリリースされてから約30年が経過しています。Python 2からPython 3への移行はコミュニティ全体でほぼ10年を要し、その過程は悪夢のようで、移行に関わった企業にとって非常に苦痛なものでした。私の認識では、言語自体に十分な構造がなく、あるバージョンから別のバージョンへのプログラム移行が容易に自動化できるようには設計されていなかったのです。これは、Pythonが静的解析を念頭に設計されていなかったためであり、サプライチェーン向けのプログラミング言語としては、静的解析の品質が非常に高いことが求められます。なぜなら、あなたのプログラムは長期間にわたって運用されるべきだからです。サプライチェーンには、「3か月待て。コードを書き直すから」といった余裕はなく、全速力で稼働中の列車のエンジンを走行中に修理するようなものです。実際に稼働中のサプライチェーンの問題を修正するのは、まさにその通りです。システムを一時停止する余裕は決してありません.
第2のパラダイムは配列プログラミングです。サプライチェーンにおける繰り返される複雑性を制御するため、特定の種類のプログラミングエラーを回避するロジックを求めています。例えば、プログラマーが明示的に記述したループや分岐は、極めて困難な問題群に晒される危険性があります。計算時間の保証を任意のループで行えるようにすると、問題は非常に厄介になります。これは一見ニッチな問題に思えるかもしれませんが、サプライチェーン最適化においては決してそうではありません.
実例として、小売チェーンを考えてみましょう。深夜、全ネットワークの売上が完全に統合され、そのデータが最適化のためのシステムに渡されます。このシステムは、各店舗の需要予測、在庫最適化、再配置の意思決定を行うために、正確に60分のウィンドウしか持ちません。処理が完了すると、その結果は倉庫管理システムに渡され、そこで全ての出荷準備が開始されます。トラックはおそらく午前5時に積み込まれ、午前9時には店舗がすでに商品を受け取り、陳列された状態で開店します.
しかしながら、あなたには非常に厳格なタイミングがあり、その計算がこの60分のウィンドウを超えてしまうと、サプライチェーン全体の実行が危険にさらされることになります。生産現場で初めて各工程にかかる時間を把握するような事態は避けたいものです。もし、反復回数を任意に決められるループ処理がある場合、計算時間の正確な証明をするのは極めて困難になります。念頭に置いていただきたいのは、ここで扱っているのがサプライチェーン最適化であるということです。すべてをピアレビューで二重にチェックする余裕はありません。時として、パンデミックの影響で、ある国が閉鎖し、他の国が通常24時間前通知で非常に不規則に再開することがあるため、迅速な対応が求められます。
つまり、配列プログラミングとは、配列に対して直接操作を行うという考え方です。ここに示すコードのスニペットはLokadのDSLであるEnvisionコードです。内容を理解するためには、「orders.amounts」と書いたときに渡されるものが変数であり、「orders」が実際にはリレーショナルテーブル、すなわちデータベースのテーブルとして扱われるという点を理解する必要があります。例えば、最初の行では「amounts」がテーブルのカラムとなります。1行目では、ordersテーブルの各行に対して、カラム「quantity」を取り出し「price」を掛け合わせ、その結果として動的に生成される3番目のカラム「amount」を作成しているのです。
ちなみに、現代では配列プログラミングはデータフレームプログラミングとも呼ばれています。この研究分野自体は非常に古く、30〜40年、あるいはそれ以上前に始まったものです。今日では一般的にデータフレームという概念に親しみがありますが、昔から配列プログラミングという呼び名も使われていました。2行目では、まるでSQLのようにフィルタリングを行っており、ordersテーブルの日付カラムに対してフィルターを適用しています。そして「date that is greater than today minus 365」と記述することで、昨年分のデータを保持し、その後「products.soldLastYear = SUM(orders.amount)」と書いているのです。
さて、興味深い点として、productsとordersの間にはいわゆるナチュラルジョインが存在します。なぜなら、各注文の行は一つの製品とのみ関連付けられており、1つの製品は0個以上の注文行に結びついているからです。こうした構成の場合、「オーダーレベルで発生している事象の合計」を製品レベルで直接計算することができます。これが9行目で正確に行われています。構文は非常にシンプルで、余計な例外処理や複雑な技術的要素がありません。私は、このコードはデータフレームプログラミングに関して、ほぼ全く例外的な部分がないと言っても過言ではないと考えています。その後、10行目、11行目、12行目では、「LIST(PRODUCTS)」および「TO(products)」を使って、ダッシュボード上にテーブルを表示しています。
サプライチェーンにおける配列プログラミングには、多くの利点があります。まず、特定の問題群を根本から排除できることです。配列でのインデックスずれ(off-by-one)のバグは発生しませんし、並列化や分散処理が非常に容易になります。これは非常に興味深い点で、つまりプログラムを書いた後、そのプログラムをローカルマシンではなく、クラウドに存在する多数のマシン群で実行できるということです。ちなみに、これはまさにLokadで実際に行われていることです。自動並列化は極めて大きな魅力となります。
ご覧の通り、サプライチェーン最適化を行う際、計算ハードウェアの利用パターンは非常に断続的です。先ほどの小売ネットワークの例に戻ると、計算用のコンピュートパワーが必要なのは1日1時間だけであり、残りの23時間は不要であることを意味します。したがって、プログラムを実行する際には、多くのマシンに一斉に分散し、処理が完了したらその全マシンのリソースを解放して、他の計算に利用できるようにする必要があるのです。逆に、1日中多数のマシンを借り上げ、稼働時間のわずか5%しか使用しないのは非常に非効率と言えるでしょう。
多くのマシンに迅速かつ予測可能に分散し、その後処理能力を解放できるという考えは、マルチテナント構成のクラウドや、Lokadが実施しているその他の一連の仕組みが必要です。しかし何よりもまず、プログラミング言語自体がそのような協力を可能にしなければなりません。これはPythonのような汎用プログラミング言語では実現が難しいほど高度なアプローチです。これは単なる小技以上のもので、ITハードウェアコストを20分の1に削減し、実行スピードを大幅に向上させ、サプライチェーンにおけるさまざまな潜在的バグを完全に除去するという、まさにゲームチェンジャーとも言える改革です。
配列プログラミングは既にPythonのNumPyやpandasといった形で存在しており、サプライチェーン-サイエンティスト向けのdatascientistセグメントにも広く普及しています。しかし、私が疑問に感じるのは、これらが非常に重要かつ有用であるならば、なぜ言語自体の第一級市民として扱われていないのかという点です。もしNumPyを介した唯一の手段であれば、NumPy自身が第一級市民であるべきです。むしろ、NumPyをさらに超えるものが理想です。NumPyは一台のマシン上での配列プログラミングにすぎませんが、なぜ複数のマシン群を利用した配列プログラミングを行わないのでしょうか。クラウド上にアクセス可能なハードウェアがあるなら、はるかに強力で適切な手法といえます。
では、サプライチェーン最適化におけるボトルネックは何でしょうか?Goldrattの「サプライチェーンのボトルネック以外の改善は幻想である」という言葉がありますが、私もこの見解に大いに同意します。実際、サプライチェーン最適化を行う際のボトルネックは、結局のところ人間、特にLokadや私の顧客にとって簡単には育たないサプライチェーン科学者にあります。
このボトルネックとは、企業のすべての戦略や競合他社の敵対的行動を考慮に入れ、その知見を機械的に大量実行可能な数値レシピに変換できるサプライチェーン科学者のことです。私が博士課程(ちなみに最終的には修了できませんでした)に在籍していた頃、研究室の誰もが文字通りデータサイエンスを実践しており、ほとんどの人が高度な機械学習モデルのコードを書いた後、エンターキーを押して結果を待つという状況でした。もし大規模なデータセット、例えば5〜10ギガバイトを扱う場合、リアルタイム処理は不可能です。そのため、研究室全体が数行のコードを書いてエンターキーを押し、しばしばコーヒーを飲んだりオンラインで情報を探したりして、非常に低い生産性に陥っていました。
私が自身の会社を立ち上げた際、結局、プログラムの実行結果を待つために一日中コーヒーを飲むような、非常に頭の切れる人材の軍団に高額な報酬を支払う羽目にはなりたくないと考えていました。理論上は、彼らが多くの処理を並行して実行し実験を行うことも可能ですが、実際にはそのような光景はほとんど見かけません。問題解決に没頭しているときは、仮説を検証するため結果を早急に得る必要があり、極めて技術的な作業を同時に複数行うのは非常に困難です。
しかし、そこには一筋の希望がありました。データサイエンティスト、そして今ではLokadのサプライチェーン科学者は、千行に及ぶコードを書いた後で「実行をお願い」と言うのではなく、その千行のスクリプトにたった2行を追加し、実行を依頼するようになりました。このスクリプトは、数分前に実行されたものとほぼ全く同じデータセットに対して走るため、ロジックはほぼ同一で、2行分の違いだけが存在するのです。では、どのようにして数分ではなく数秒でテラバイト規模のデータを処理できるのでしょうか?その答えは、前回のスクリプト実行時に計算の中間ステップをすべて記録し、非常に安価で高速、かつ便利なSSDなどのストレージに保存しているからです。
次にプログラムを実行すると、システムはほぼ同一のスクリプトであることに気付き、差分を検出します。計算グラフの観点からはほとんど同じで、データも通常100%一致しているため、再計算が必要な部分はごく僅かに留まり、結果を数秒で出力することができます。これにより、サプライチェーン科学者の生産性は劇的に向上し、エンターキーを押して20分待つ代わりに、5〜10秒後に結果が得られ、次の作業にすぐ移ることができるのです。
これは非常に一見取っ付きにくい内容のように思えるかもしれませんが、実際には生産性に10倍の影響を与えるものであり、非常に大きなインパクトがあります。つまり、Lokadが発明したわけではない巧妙なトリックを使い、計算という生のリソースを、メモリとストレージという別のリソースに置き換えているのです。基本的なコンピューティングリソースとしては、計算、メモリ(揮発性または永続性)、そして帯域幅があり、これらはクラウドコンピューティングプラットフォームでリソースを購入するときに支払う対象となります。実際、あるリソースを別のリソースに置き換えることが可能で、その目的はコストパフォーマンスを最大化することにあります。
多くの人がインメモリコンピューティングの利用を主張しますが、私はそれは的外れだと思います。というのも、インメモリコンピューティングはある特定のリソースに重点を置く設計を意味するため、他のリソースとのトレードオフが発生するからです。通常の汎用プログラミング言語でもこのようなことは可能ですが、すべて手動で行う必要があり、その場合、その操作を担うのはプロのソフトウェアエンジニアであるべきです。サプライチェーン科学者がプラットフォームの基本的な計算リソースに関してこのような低レベルな操作を行うことはまずありません。これはプログラミング言語自体のレベルでエンジニアリングされるべきものです。
さて、次は確率的プログラミングについて話しましょう。定量的サプライチェーンのビジョンを紹介した第2回目の講義では、あらゆる可能な未来を検討する必要があるというのが私の第一の要件でした。この要件に対する技術的な解答がprobabilistic forecastingです。未来はすべて可能であるものの、その確率は一様ではありません。不確実性を伴う計算を行うための代数体系が必要なのです。私がExcelを厳しく批判する理由の一つは、Excelや他の最新のクラウドベースのスプレッドシートでは、不確実性を単なる数値以上のもので表現するのが非常に困難であるという点にあります。
この小さなスニペットでは、乱数変数の代数、すなわちEnvisionのネイティブ機能を示しています。1行目で平均2の離散ポアソン分布を生成し、それを変数Xに代入します。次に、同様な手法で別のポアソン分布Yを生成し、XとYの乗算としてZを計算します。この乱数変数の乗算という操作は非常に奇妙に思えるかもしれません。では、サプライチェーンの視点から、このような操作が一体何のために必要なのでしょうか?例を挙げてみましょう。
例えば、自動車部品のアフターマーケットにおいてブレーキパッドを販売しているとします。人々はブレーキパッドを単品で購入するのではなく、2個または4個で購入します。したがって、予測を行う際には、顧客が特定のブレーキパッドを購入する確率、すなわち需要が0個、1個、2個、3個、4個…と観測される確率を予測する必要があります。これが最初の乱数変数となります。その後、顧客が実際に2個または4個を購入するかどうかを表す別の確率分布が存在し、例えば50対50であったり、2個購入が10%で4個購入が90%であったりします。この二つの角度があり、ブレーキパッドの総消費量を求めるためには、顧客が現れる確率と、2個または4個を購入する確率分布を掛け合わせる必要があるのです。
ここでは、二つの乱数変数が独立していると仮定しています。ちなみに、この乱数変数の乗算は数学的には離散畳み込み(discrete convolution)として知られています。スクリーンショットに示すように、Envisionによって生成されたダッシュボードでは、最初の3行でこの乱数代数の計算を行い、4行目、5行目、6行目でその結果をウェブページ上に、スクリプトによって生成されたダッシュボードに表示しています。例えば、ExcelのグリッドのようにA1、B2などがプロットされています。LokadのダッシュボードはExcelのグリッドと同様の構成で、B、Cなどの列と、1、2、3、4、5の行で配置されています。
ご覧の通り、離散畳み込みZは非常に奇妙でピークの激しいパターンを示しており、これはパックや複数単位で購入できるサプライチェーンにおいて非常によく見られる現象です。このような状況では、通常、ロットやパックに関連する乗数的なイベントの要因を分解するほうが望ましいです。言語自体が第一級市民として、こうした機能を自在に扱える必要があるのです。これがまさに確率的プログラミングの本質であり、Envisionでそれを実装した方法です。
さて、次は微分可能プログラミングについて議論しましょう。ここで一つ前置きさせてください。聴衆の皆さんがこの内容を完全に理解することは期待しておらず、その点についてはお詫び申し上げます。決して皆さんの知性が不足しているのではなく、このトピックは一連の講義全体に値するほどの内容だからです。実際、今後の講義計画を見ると、微分可能プログラミングに特化した一連の講義が用意されています。今回は非常に高速かつ多少暗号的な説明となるため、あらかじめご了承ください。
ここで注目すべきサプライチェーンの問題、すなわち自社製品間のカニバリゼーションと代替について進めていきます。これらの問題は非常に興味深く、遍在する時系列予測が最も残酷な形で失敗する原因でもあります。なぜなら、たとえばバックパックなど特定の商品について13週間先の予測が可能かどうか、顧客や見込み客から問い合わせがあるからです。私は「はい、できます」と答えますが、明らかに1つのバックパックだけの需要を予測しようとしても、その需要は他のバックパックとの関係に大きく依存します。もし1種類のバックパックしかなければ、全需要がその商品に集中するかもしれません。しかし、10種類のバリエーションを導入すれば、当然ながら多くのカニバリゼーションが発生します。参照数を10倍にしたからといって総売上が10倍になるわけではないのです。従って、カニバリゼーションと代替の現象が起きるのは明らかであり、これらはサプライチェーン全体に広く見られます。
カニバリゼーションや代替をどのように解析するのでしょうか?Lokadで私たちが行っている方法は、唯一の方法だとは主張しませんが、確実に効果がある一例として顧客と製品を結ぶグラフに着目することです。なぜなら、カニバリゼーションは同じ顧客に対して複数の製品が競合する場合に発生するからです。つまり、顧客が何らかのニーズを持っているものの好みがあり、適合する製品群の中から1つだけを選択するという現象がカニバリゼーションの本質なのです。
これを解析するには、まず売上の時系列ではなく、顧客と製品間の過去の取引を結ぶグラフを解析する必要があります。実際、ほとんどのビジネスではこのデータが容易に入手可能です。eコマースでは、販売する各ユニットごとに顧客が特定されているのは言うまでもありません。B2Bでも同様です。さらに、B2Cの小売業においても、近年の小売チェーンはロイヤルティプログラムを導入しており、カードを提示する顧客のおおよそ二桁の割合が識別されるため、誰が何を購入しているかが把握できます。全トラフィックの100%ではなくても、取引の10%以上で顧客と製品のペアが分かれば、この種の解析には十分です。
この比較的小さなコード断片では、顧客と製品間の親和性分析について詳述します。これは、カニバリゼーション解析を行う上での基礎的なステップそのものであり、実際に何が行われているのかを見ていきましょう。
1行目から5行目までは非常に平凡な処理です。取引履歴を含むフラットファイル、つまり日付、製品、顧客、数量の4列を持つCSVファイルを読み込んでいるだけです。基本的な処理であり、例をより具体的にするためにすべての列を利用しているわけではありません。取引履歴では、すべての取引において顧客が特定されていると仮定しています。単にテーブルからデータを読み込んでいるのみです。
次に、7行目と8行目では、製品用のテーブルと顧客用のテーブルを単に作成しています。実際のプロダクション環境では、通常これらのテーブルは新たに作成せず、別のフラットファイルから読み込むでしょう。ここでは例をできるだけ単純にするため、取引履歴で観測された製品から製品テーブルを抽出し、顧客についても同様の処理を行っています。ご覧の通り、極めてシンプルにするためのトリックです。
続いて、10行目、11行目、12行目ではラテン空間に関わる処理が登場し、少し分かりにくくなります。まず、10行目で64行からなるテーブルを作成しています。このテーブルには何も含まれておらず、ただ64行という事実によって定義されるだけです。つまり、カラムを持たない多数の行がある単なるプレースホルダーのようなテーブルです。それだけではほとんど役に立ちません。次に「P」は、基本的にすべての組み合わせを生成する直積(カルテシアン積)の数学的操作を表しており、製品テーブルの各行とテーブル「L」の各行の組み合わせからなるテーブルです。結果として、このテーブル「P」は製品テーブルよりも64行多くなり、顧客に対しても同様の操作が行われ、追加次元である「L」によってテーブルが膨らまされるのです。
これは、私が学習するラテン空間の基盤となる部分であり、各製品ごとに64の値からなるベクトル、そして各顧客ごとにも同様の64値ベクトルを学習するというものです。顧客と製品間の親和性を知りたい場合、両者のドット積(内積)を計算すればよいのです。ドット積とは、2つのベクトルの各要素同士を乗算し、その結果を合計する計算のことです。非常に技術的に聞こえるかもしれませんが、実際は要素ごとの乗算とその合計、つまりこれがドット積なのです。
ここで言うラテン空間とは、学習したいパラメータを含む空間を指す、少し作り話っぽい派手な専門用語に過ぎません。微分可能プログラミングの本当の魔法は、14行目から18行目のわずか5行で発揮されます。ここでは「autodiff」と「transactions」という1つのキーワードを用いて、このテーブルが観測すべき対象であることを示しています。このテーブルを1行ずつ処理して学習プロセスを進めるのです。このブロック内で、一連のパラメータを宣言します。パラメータとは、学習対象となる数値であり、まだその値は分かっていないものです。これらはランダムな値で初期化されるだけです。
ここでは「X」、「X*」、そして「Y」を導入しています。「X*」が具体的に何をしているのかには深入りしません(質問の中で触れるかもしれません)。損失関数となる表現、つまり合計値を返しており、協調フィルタリングや行列分解の考え方は、二部グラフ上の全てのエッジに適合するラテン空間を学習するという単純なものです。技術的には少し難解に思えるかもしれませんが、サプライチェーンの視点から見ると非常にシンプルな内容です。すなわち、製品と顧客間の親和性を学習しているのです。
非常に難解に思えるかもしれませんが、どうかお付き合いください。後ほど、より丁寧な入門講義も行います。全体がたった5行で完結しているのは本当に驚くべきことです。ここで「5行」と言っても、背後で莫大な複雑さを持つサードパーティライブラリの呼び出しによって全ての知識を隠蔽しているわけではありません。いや、ここでは「autodiff」と「params」という2つのキーワード以外に機械学習の魔法は一切存在しません。「autodiff」は微分可能プログラミングが行われるブロックを定義するために使われ、ちなみにこのブロック内ではあらゆるプログラムを実装可能です。次に、「params」で問題を宣言するだけです。ご覧の通り、背後で百万行にも及ぶライブラリが全ての作業をしているわけではなく、必要なすべての知識がこの画面上に露呈しているのです。これがライブラリとプログラミングパラダイムの違いであり、プログラミングパラダイムは、膨大なサードパーティライブラリに頼ることなく、数行のコードでカニバリゼーション解析のような非常に高度な機能を実現できるのです。それは問題を超越し、非常にシンプルにすることで、複雑に見えるものが実際には数行で解決できるということを意味します。
さて、微分可能プログラミングの仕組みについて少し説明しましょう。ここでのポイントは2つあります。一つは自動微分です。工学の訓練を受けた方なら、微分を計算する方法としてシンボリック微分と数値微分の2種類を見たことがあるでしょう。例えば、xの二乗の場合、xに関する微分は2xとなる、これがシンボリック微分です。そして、関数f(x)の微分を求める場合、f’(x) ≈ (f(x + ε) - f(x)) / εという近似を用いる数値微分があります。どちらの方法も、ここで目指す目的には適していないのです。シンボリック微分は、微分そのものが元のプログラムよりもはるかに複雑なプログラムになってしまうという問題があり、数値微分は数値的に不安定で、多くの不具合を生じさせる可能性があるのです。
自動微分は1970年代に生まれた素晴らしいアイデアであり、ここ10年で再発見され、世界中に広まっています。任意のコンピュータプログラムの微分を計算できるという考えは衝撃的であり、さらに驚くべきことに、その微分プログラムは元のプログラムと同じ計算量で動作するのです。微分可能プログラミングは、自動微分と学習対象となるパラメータの組み合わせに過ぎません。
では、どのように学習するのでしょうか? 微分が可能になるということは、勾配を逆伝播させることができ、確率的勾配降下法を用いてパラメータの値を微調整できるということです。これにより、何度も確率的勾配降下法の反復を重ねることで、徐々に意味のある、学習または最適化すべきパラメータへと収束していくのです。
微分可能プログラミングは、今回のように顧客と製品間の親和性を学習する問題だけでなく、制約下での最適化などの数値最適化問題にも利用でき、そのパラダイムとしてのスケーラビリティも非常に高いのです。ご覧の通り、この側面はEnvisionにおいてファーストクラス市民として扱われています。ちなみに、Envisionの構文に関してはまだ改善の余地がある部分もあるので、完全な形をすぐに期待しないでください。調整中の点はありますが、本質は確立されています。ここでは、まだ進化中の細部については触れません。
では、次にシステムの本番準備に関連する別の問題に移りましょう。通常、サプライチェーン最適化ではハイゼンバグに直面します。ハイゼンバグとは、最適化が実行されても無意味な結果を生み出してしまう苛立たしいバグのことです。たとえば、夜間に在庫補充のためのバッチ計算を実行し、翌朝になってその結果の一部が無意味で高コストなミスを引き起こしていることに気づく、という状況です。同じ問題を再発させないためにプロセスを再実行しても、問題が再現せずハイゼンバグは姿を消してしまうのです。
一見、奇妙な例外ケースのように思えるかもしれませんが、Lokadの初期数年間はこのような問題に何度も直面していました。特にデータサイエンス系のサプライチェーンプロジェクトが、未解決のハイゼンバグによって失敗するのを何度も見てきました。生産環境でバグが発生し、現場で問題を再現できなかったために解決が先送りにされ、数ヶ月間パニック状態に陥った後、最終的にはプロジェクトがひっそりと終了し、皆がExcelスプレッドシートに戻ってしまったのです。
論理の完全な再現性を達成するためには、コードとデータの両方をバージョン管理する必要があります。ソフトウェアエンジニアやデータサイエンティストであれば、コードのバージョン管理の概念には馴染みがあるでしょう。しかし、プログラム実行時にどのバージョンのコードとデータが使用されているかを正確に把握するためには、すべてのデータについてもバージョン管理を行う必要があります。新たな取引やその他の要因でデータが変更されるため、翌日には問題を再現できなくなり、そもそもバグを引き起こした条件が失われてしまうからです。
プログラミング環境が、本番時の論理とデータを特定の時点で正確に再現できることを保証しなければなりません。これにはすべてのものの完全なバージョン管理が必要です。再び申し上げますが、これを実現するためにはプログラミング言語とスタックが連携する必要があります。プログラミングパラダイムがスタックのファーストクラス市民でなくても実現可能ですが、その場合はサプライチェーン科学者が自身のプログラミング方法や実装に非常に注意深くならなければなりません。さもなければ、結果の再現は不可能になります。これは、すでにサプライチェーン自体から大きなプレッシャーを受けているサプライチェーン科学者にとって、誤って複雑さを抱えるリスクを増大させるものです。彼らに、自分自身の結果を再現できないというような偶発的な複雑性に対処させたくはありません。Lokadでは、これを「タイムマシン」と呼び、過去の任意の時点で全てを再現できるようにしています。
注意すべきは、昨晩の出来事だけを再現することではありません。時として、事実が経過した後にミスに気づくこともあります。例えば、仕入先に対してリードタイム3ヶ月の発注を出した場合、その発注が無意味であったと3ヶ月後に判明するかもしれません。その原因を突き止めるためには、その架空の発注を作成した3ヶ月前まで遡らなければならないのです。これは直近数時間の作業だけでなく、過去1年分の実行履歴全体のバージョン管理が求められるということです。
さらに、サプライチェーンを狙ったランサムウェアやサイバー攻撃の増加という懸念もあります。これらの攻撃は極めて破壊的で、多大なコストを伴う可能性があります。ソフトウェア主導のソリューションを実装する際は、自社およびサプライチェーンがサイバー攻撃やその他のリスクに対してより脆弱になっていないかを慎重に考慮する必要があります。この観点から、ExcelやPythonは理想的とは言えません。これらのコンポーネントはプログラム可能であるため、数多くのセキュリティ上の脆弱性を抱える可能性があるのです。
サプライチェーンの問題に取り組むデータサイエンティストやサプライチェーン科学者のチームがいる場合、ソフトウェア業界で一般的な慎重かつ反復的なピアレビューのプロセスに十分な時間を割く余裕はありません。たとえば、関税が一夜にして変わったり、倉庫が浸水したりしたときには、迅速な対応が求められます。数週間をかけてコードの仕様書やレビューを行っている余裕はないのです。問題は、企業に対して偶発的に損害を与える可能性のあるプログラミング能力を、元来そのリスクをはらむ人々に与えてしまう点にあります。不正意図の従業員がいる場合はさらに悪化しますが、たとえそれを脇に置いたとしても、誰かが誤ってITシステムの内部情報を漏洩してしまう問題は依然として残ります。サプライチェーン最適化システムは、その定義上、企業全体の大量のデータにアクセスできるため、このデータは資産であると同時に負債でもあるのです。
求めているのは、安全なプログラミングを促進するプログラミングパラダイムです。あなたは、実行できない操作の一群が存在するプログラミング言語を望んでいます。例えば、なぜサプライチェーン最適化のためのシステムコールを実行できるプログラミング言語が必要なのでしょうか?Pythonはシステムコールを実行できますし、Excelも同様です。しかし、初めからそのような機能を持つプログラム可能なシステムを求める理由は何でしょうか?自分の足を撃つために銃を買うようなものです。
サプライチェーン最適化に不要なため、全く必要としない機能が存在するものを求めています。もしこれらの機能が存在すると、大きな負債となります。設計上安全なプログラミングを強制するツールなしにプログラム可能な機能を導入すると、サイバー攻撃やランサムウェアのリスクが増大し、事態を悪化させることになります。
もちろん、サイバーセキュリティチームの規模を倍にすることで補うことは可能ですが、それは非常に高コストであり、緊急のサプライチェーン状況に直面した際には理想的ではありません。通常のプロセス、レビュー、承認にかける時間がない中で、迅速かつ安全に行動する必要があります。また、ヌル参照例外、メモリ不足エラー、オフバイワンのループ、副作用などの陥りがちな問題を排除する安全なプログラミングも求められています。
結論として、ツールは極めて重要です。諺にもあるように、「銃戦に剣を持っていっても仕方がない」のです。大学で学んだものだけでなく、適切なツールとプログラミングパラダイムが必要なのです。サプライチェーンのニーズを満たすためには、プロフェッショナルで生産グレードのものが求められます。劣悪なツールでも多少の結果は得られるかもしれませんが、決して優れたものにはなりません。素晴らしいミュージシャンは、スプーンだけで音楽を奏でることができても、適切な楽器を使えばはるかに素晴らしい音楽を作り出せるのです。
さて、質問に進みましょう。なお、動画と私が皆さんの質問を読む間には約20秒の遅延があるため、ストリームに若干のラグが生じることにご注意ください。
質問: オペレーションズリサーチの観点から、動的計画法はどうなっているのでしょうか?
動的計画法は、その名前にもかかわらずプログラミングパラダイムではなく、むしろアルゴリズムの手法です。あるタスクを実行したり、特定の問題を解決する際に、同じ部分操作を非常に頻繁に繰り返すという考え方です。これは、前述した空間と時間のトレードオフの具体例であり、計算側の時間を節約するために、メモリに少し投資するというものです。1960年代や1970年代にまでさかのぼる初期のアルゴリズム手法の一つでもあります。良い手法ではありますが、「動的」という名称は実際にはあまり動的な要素がなく、プログラミングそのものというよりもアルゴリズムの考案に近いものです。ですから、名前にも関わらず、私にとってはプログラミングパラダイムとは言えず、特定のアルゴリズム手法にすぎないのです。
質問: ヨハネスさん、全ての優れたサプライチェーンエンジニアが持つべき参考書をいくつか教えていただけますか?残念ながら、私はこの分野では新米で、現在はデータサイエンスやシステムエンジニアリングに注力しています。
既存の文献については非常に賛否両論があります。最初の講義では、サプライチェーンに関する学術研究の頂点だと信じる二冊の本を紹介しました。もし二冊の本を読みたいのであれば、それらを読めばいいでしょう。しかし、これまで読んできた本には常に問題がありました。基本的に、理想化されたサプライチェーンのためのおもちゃのような数値レシピのコレクションを提示する人々がいて、これらの本はサプライチェーンを正しい視点から捉えておらず、本質的に「手に負えない問題」であることを完全に見落としているのです。方程式、アルゴリズム、定理、証明といった非常に技術的な文献も広く存在しますが、私にはその本質を全く捉えていないように思えます。
次に、コンサルタント風のサプライチェーンマネジメントに関する書籍があります。これらは2ページに1回の割合でスポーツの例えを使うため、一目でそれと分かります。SWOT(Strengths, Weaknesses, Opportunities, Threats)の2x2のような単純な図表など、あらゆる単純化されたダイアグラムが使われており、これらは質の低い思考方法だと考えています。これらの書籍の問題点は、サプライチェーンが手に負えない事業であるという理解は優れているものの、人が操るゲームであり、あらゆる奇妙な事態が起こりうるという点を理解していて、ある意味賢い方法を提示している点は評価できるものの、実際の行動に移すための具体性に欠ける点です。結局、「より良いリーダーになれ」、「もっと賢くあれ」、「より多くのエネルギーを持て」というメッセージに終始し、私にとっては実行可能なものではなく、ソフトウェアのように非常に価値ある要素に変換できるものが提示されていないのです。
というわけで、最初の講義に戻ると、もし二冊の本を読んでみたいのであれば読んでもいいのですが、それが時間の有効な使い方かどうかは疑問です。人々が何を書いてきたかを知るのは良いことです。しかし、コンサルタント系の文献の中で、私の個人的なお気に入りはKatanaの著作です。これは最初の講義では触れていませんでした。すべてが悪いわけではなく、コンサルタント風であっても才能ある人はいます。Katanaの著作をご覧ください。彼は動的サプライチェーンに関する本を出版しており、その本は参考文献として記載する予定です。
質問: カニバリゼーションやアソートメントの意思決定において、問題が簡単に並列化できない場合、どのように並列処理を利用するのでしょうか?
なぜ容易に並列化できないのでしょうか?確率的勾配降下法は、並列処理が非常に容易です。確率的勾配のステップはランダムな順序で実行でき、同時に複数のステップを踏むことが可能です。したがって、確率的勾配降下法に基づくものは、並列処理が極めて容易に実現できると考えています。
カニバリゼーションに対処する際により困難なのは、別の種類の並列処理、すなわち何が先に来るかという点への対応です。もしこの製品を先に投入して予測を行い、その後に別の製品を投入すると、全体の状況が変化してしまいます。答えとしては、全体の状況を一括して扱える方法が必要なのです。「まずこの製品を投入して予測し、次に別の製品を投入して再度予測し、最初の予測を修正する」というのではなく、一度にすべてを一括して処理すべきです。より多くのプログラミングパラダイムが求められます。今日紹介したプログラミングパラダイムは、そのために大いに役立つでしょう。
品揃えの意思決定に関しては、この種の問題は並列処理に大きな困難をもたらしません。世界規模の小売ネットワークがあり、全店舗の品揃えを最適化したい場合でも、各店舗での計算を並列に実行することが可能です。一店舗ずつ順番に最適化していくやり方は望ましくなく、それは誤った方法です。しかし、ネットワーク全体を並列に最適化し、全ての情報を伝播させた上で繰り返すことができます。さまざまな技術があり、適切なツールを用いれば、これをより容易に実現できるのです。
質問: グラフデータベースのアプローチを使用していますか?
いいえ、技術的かつ標準的な意味でのグラフデータベースは使用していません。市場には非常に興味深いグラフデータベースが多数存在しますが、Lokad内部では、統一されたモノリシックなコンパイラスタックを通じた完全な垂直統合により、従来のスタックに見られるあらゆる要素を完全に排除しています。これにより、計算性能、すなわちハードウェアに非常に近い性能を実現しています。これは、私たちが非常に優れたコーダーであるためではなく、従来存在していたほぼ全ての層を排除したためです。Lokadでは文字通りデータベースを一切使用していません。永続性のためのデータ構造の整理に至るまで、すべてを担うコンパイラがあります。少々奇妙な方法ですが、その方が非常に効率的であり、クラウド上の複数のマシンに対してスクリプトをコンパイルするという意味でも非常にうまく機能しています。ハードウェアの観点では、ターゲットプラットフォームは一台のマシンではなく、マシンのフリートなのです。
質問: Power BI のように、Pythonコードや勾配降下法、貪欲法などの関連アルゴリズムも実行するものについて、どうお考えですか?
ビジネスインテリジェンス、特にPower BIに関連するものに対して私が抱く問題は、それらがサプライチェーンに対して不適切なパラダイムを採用している点です。全ての問題をハイパーキューブとして捉え、単に次元をスライス&ダイスするだけです。本質的には、表現力の問題があり、非常に限定的です。結果として、ハイパーキューブの表現力が極めて乏しいため、中間にPythonを挟む必要が生じます。表現力を回復するためにPythonを加えるのですが、先の質問で述べたように、現代のエンタープライズソフトウェアは層が多すぎるという呪いを抱えています。追加する層はそれぞれ非効率やバグを生み出します。Power BIとPythonを組み合わせると、層があまりにも多くなってしまうのです。まず、Power BIはすでに他のシステムの上に乗っており、その上にPower BI、さらにその上にPythonが存在します。しかし、Pythonは独立して動作しているのでしょうか?いいえ、PandasやNumPyといったPythonライブラリも使用せざるを得ません。結果として、Python内でも層が積み重なり、数十もの層が生じ、どの層にもバグが潜む可能性があって、状況は非常に悪夢的になってしまうのです。
私は、膨大な数のスタックを重ねるという解決策を支持していません。C++では、さらなる間接レイヤーを追加することでどんな問題も解決できるというジョークもありますが、これはもちろん皮肉交じりの発言です。しかし、コア設計が不十分な製品に対して、問題に正面から取り組むのではなく、不安定な基盤の上に次々と機能を重ねていくアプローチには断固反対です。そうすれば、生産性が低下し、解決できないバグとの永続的な戦いに巻き込まれ、最終的には保守性においても悪夢のような状態になってしまいます。
質問: バックパックなどの各製品の需要予測アルゴリズムに、協調フィルタリング分析の結果をどのように取り込むことができるのでしょうか?
申し訳ありませんが、このトピックについては次回の講義で取り上げます。短く言えば、既存の予測アルゴリズムにこれを取り込むのは望ましくありません。はるかにネイティブに統合されたものを用意すべきです。従来の予測手法に戻すのではなく、従来の方法を廃棄し、全く異なる革新的な手法を採用するべきなのです。しかし、この点については後の講義で詳しく議論します。今日は説明しきれないほどの内容になります。
これで今回の講義は終了です。ご参加いただき、誠にありがとうございました。次回の講義は1月6日(水)、同じ時間、同じ曜日に行われます。私自身はクリスマス休暇を取る予定ですので、皆さんに素晴らしいクリスマスと新年をお祈りします。講義シリーズは来年も継続いたします。ありがとうございました。