RAKSUL TechBlog

RAKSULグループのエンジニアが技術トピックを発信するブログです

めぐろLT 2024 振り返り

めぐろLT 2024 をふりかえる

こんにちは、ラクスル星野です。 めぐろLT参加者のみなさん、アドベントカレンダー参加者のみなさん、おつかれさまでした。

本記事は、めぐろLTアドベントカレンダー2024の最終日の記事です。 締めくくりとして2024年のめぐろLTをテーマを振り返り総括などしたいと思います。

本文

めぐろLTは connpass の概要にもある通り

  • 月一開催
  • 各社持ち回りで、開催場所が変わる

という運用で「LTをする」以外はあまりルールを設けず各社に開催していもらっている集まりです。

2024 年の開催を振り返ると

開催日 開催場所 テーマ
2024/01/30(火) ペライチ@御徒町 2024年の抱負
2024/02/28(水) ラクーンホールディングス@日本橋 おすすめ書籍紹介LT
2024/03/12(火) ラクスル@目黒 これからエンジニアになる人へ贈ることば
2024/04/18(木) ラクスル@目黒 データ分析よろず会
2024/05/27(月) ハコベル@日本橋 みんなのしくじり大賞
2024/06/25(火) オロ@目黒 みんなのオーバーエンジニアリング供養
2024/07/29(月) HRBrain@目黒 技術発信
2024/08/23(金) ラクーンホールディングス@日本橋 教えたくないことを教えちゃうLT
2024/09/26(木) ペライチ@御徒町 生成AIよもやま話
2024/10/24(木) ラクスル@目黒 PM / PdMあれこれ
2024/11/15(金) オロ@目黒 今年一番の〇〇聞いてくれ
2024/12/12(月) HRBrain@目黒 LT忘年会2024

と、いろいろなテーマがあったのだなあと、思い出深いです。

(個人的に、オーバーエンジニアリング供養会での超絶CSSの発表がすごく印象に残っています)

月一開催ということで、全12回の開催がありました。それぞれのテーマに沿ったLTが行われ、参加者の皆さんには多くの知識や情報を共有いただきました。 「めぐろLT」という connpass グループのメンバー数も 2024/12 現在 544 人と、たくさんの方に興味をもっていただけて嬉しいです。こんなにいたんですね。

去年のアドベントカレンダーでも触れましたが、めぐろLTを立ち上げた動機が「普段のチームとは違う人達と交流を持ちたい」だったので、多くの方に興味関心を持って参加していただけてとても嬉しいです。

反省と学び

せっかくなので、LTコミュニティを2年ほどやってきて思う反省や学びなどを書いておこうかなと思います。

オフラインの速さ

めぐろLTは「自分たちも会社で開催してみたい」と手を上げてくれた会社を取り込みながら、ここまで大きくなってきたという経緯があります。 インターネット上で知らない人に声を掛けるというのハードルが高いのではないでしょうか。一方でLTに興味のある人が集まる場での対面コミュニケーションでは

  • 「やりたい」「じゃあやっちゃいますか」のやり取りが速い
  • 「星野さん、この方がLT会やりたいそうですよ」というような紹介が発生する

などオフラインならでわの出会いが頻繁にあり、速度を感じました。

オンラインのイベントは便利だし、自分も大好きですが、やっぱりオフラインにはオフラインの面白さやスゴさがあるなあと実感しています。 今後も、この両方の良さをうまくいかしていきたいと思っています。

先にも書きましたが、コミュニティのメンバーは500人ほどいる一方で毎回各会場の都合で30-40人程度の募集となっています。 会社によってはオンライン募集も併用でおこなったりなど工夫をこらしてくれていますが、30人程度のクローズドな会だからこそ話しやすい内容もあるしなあという気持ちもあり、良い落とし所を探っていきたいです。

各会の振り返りなど、もっと共有する雰囲気作っても良かった

めぐろLTでは各社持ち回りの会は、意図的に「ご自由にどうぞ」というスタンスで運用しています。 これは、各社や各会場にそれぞれの事情や、なぜLTを開くのかなどの目的付けなどがあり、あまり強くルールや規約をつくっても互いにやりづらいだろうという思いがあるからです。

イベント開催後の振り返りなども、各社でされているのかと思うのですが、特に運営会社間で共有を強制していません。

なのですが、たとえば

  • 参加者30人の予定に対して、飲み物・食べ物をどれくらい発注して、足りた・不足した
  • ケータリングになにを提供し、評判が良かった・悪かった
  • 音響Tips
  • 会場案内テクニック

など、イベントを開くときに把握しておきたいちょっとしたさじ加減などが共有されていると、新規や久々のLT会を開くときの参考になりそうです。 「めぐろLT」というコミュニティに参加してイベントを開く共催企業の皆様へ、このグループでやるメリットをより提供できるのかもと思っています。

あってよかったガイドライン

めぐろLTでは、

  • LT開催したいという企業向け開催ガイドライン
  • LT会の全参加者向けハラスメントポリシー

を用意しています。 「これはどう判断すべきだろう」ということが起きたとき、都度判断するのではなく、ガイドラインやポリシーにどう書いてあるかで判断する、という方針を取っています。

正直、はじめはわざわざガイドラインをちゃんと作らなくてもゆるく運営できるのではないかという気持ちは少なくともありました。 しかしこういうものがあった結果、思考のコストを低くし物事を判断できました。長くコミュニティを運用する上でこういったものを早く用意しておくことは結構楽なのだという実感があります。

使うツール

各社とやり取りで無料版Slackをつかっているけど、過去のログが保持されないなどの理由でDiscordのほうが良かったかな……といまでは思っています。

まとめ

めぐろLTアドベントカレンダー2024、最終日までお読みいただき、ありがとうございました。

次回めぐろLTは 2025/01/23 に日本橋のラクーンホールディングスで開催します! https://meguro-lt.connpass.com/event/338641/

まだ参加したことがないが気になるという方もTwitterの #めぐろLT というハッシュタグで雰囲気をなんとなく感じていただけるかもしれません。参考にしていただければ!

ぜひ振るってご参加ください。

2025年もめぐろLTをよろしくお願いいたします。 では、良いお年を!!

Spike-and-Slab事前分布の概要

この記事はノバセル Advent Calendar 25日目、最終日です。

こんにちは。ノバセルでデータサイエンティストをしている石井です。
変数が重要か否かを明確化したい場面において利用することがあるSpike-and-Slab事前分布を題材として、概要をライトに書き留めます。

はじめに

Spike-and-Slab事前分布はベイズ推論において事前分布と称されるもの (詳細は後述)の一種であり、変数選択やCausalImpactの利用を通して馴染みのある分析者も一定いらっしゃるかと思います。

本論

Spike-and-Slab事前分布について6部構成で概要を記します。

1. 事前分布の役割

2. Spike-and-Slab事前分布 (縮小事前分布)とは

3. なぜSpike-and-Slab事前分布なのか

4.  ビジネス上の期待される価値

5.  重回帰分析のモデル構造

6.  推定結果の特徴

1. 事前分布の役割

主な役割は以下の通りです。

  • 過学習の抑制
    • パラメータが極端な値をとらないように抑制
  • 専門知識の反映
    • 「このパラメータはこれ程大きくはならないだろう」「正の値をとりやすい」などのドメイン知識を反映
  • 推定結果の安定化
    • サンプルサイズが少ない場合などにデータだけでは十分に推定できないパラメータを、事前分布によって安定的に推定

ベイズ推論では、事前分布による初期の仮定が、観測データから得られる情報によってアップデートされ最終的な事後分布が得られる仕組みになっています。

2. Spike-and-Slab事前分布 (縮小事前分布)とは

ベイズ推論での変数選択を得意とする事前分布の1種類であり、各回帰係数 (パラメータ) $\beta_j$の事前分布を以下の形で表現可能な混合事前分布です。


\begin{eqnarray}
\beta_j &\sim& \pi \cdot \delta_0(\beta_j) + (1 - \pi) \cdot p_{\text{slab}}(\beta_j)
\end{eqnarray}

  • $\delta_0(\beta_j)$ は $\beta_j = 0$ に点質量を持つ「スパイク」部分
  • $p_{\text{slab}}(\beta_j)$ はゼロから離れた値を許容する連続分布 (「スラブ」部分)
  • $\pi$ はスパイクとスラブの混合比率

また、上記のようにパラメータを0へと縮小する性質を持つ事前分布を縮小事前分布と呼称します。

3. なぜSpike-and-Slab事前分布なのか

馬蹄分布やLaplace分布も代表的な縮小事前分布ではあるが、以下の観点よりSpike-and-Slab事前分布を利用できることが理想的であるためです。

  • Laplace分布: 本来は重要である変数も過度に0へ縮小する傾向
  • 馬蹄分布: あくまでもSpike-and-Slab事前分布に対し連続関数で近似したもの (ただし、比較的計算コストが低い)

4. ビジネス上の期待される価値

以下の性質より「納得感のある意思決定」に資することが期待される場面があります。

① ベイズ推論の性質

  • 推定されたパラメータの不確実性を定量的に示せるため期待値コントロールを行いやすい。

② 縮小事前分布の性質

  • 重要な変数に焦点を当てることが可能であるため結果の解釈性が高い。 (セクション6 「推定結果の特徴」と繋がる話)
    • 変数が重要か否かを明確化したい場面において、Spike-and-Slab事前分布が価値を発揮する印象。(特にLaplace分布と比較した場合)

5. 重回帰分析のモデル構造

Spike-and-Slab事前分布を重回帰分析にどのように組み込めるのかをグラフィカルモデルで示します。
$\\pi$と$\\beta$により表現される$\\beta\_probabilistic$がSpike-and-Slab事前分布を用いて推定される係数です。

階層モデルで表現されており、以下が詳細です。

1.  指示変数 $z_j \in \{0,1\}$ を導入

  • $z_j = 1$ なら変数 $j$ は「採択」
  • $z_j = 0$ なら変数 $j$ は「非採択」

2.  指示変数 $z_j$を定義


\begin{eqnarray}
z_j &\sim& \mathrm{Bernoulli}(\pi)
\end{eqnarray}

3. $z_j$ に応じて $\beta_j$ の事前分布を切り替え


\begin{eqnarray}
\beta_j \mid z_j &=&
\begin{cases}
0, & \text{if } z_j = 0 \\
\mathcal{N}(0, \sigma^2), & \text{if } z_j = 1
\end{cases}
\end{eqnarray}

(例として「スラブ」を正規分布とした場合)

上記のように表現することで
「$z_j = 0 \Rightarrow \beta_j = 0$」
「$z_j = 1 \Rightarrow \beta_j \sim \mathcal{N}(0, \sigma^2)$」
となり、下記のようにスパイク (真に0)とスラブ (0でない連続分布)の混合を実現できます。


\begin{eqnarray}
\beta_j &=&
\begin{cases}
0, & \text{with probability } \pi \\
\text{drawn from slab distribution}, & \text{with probability } (1 - \pi)
\end{cases}
\end{eqnarray}

6. 推定結果の特徴

推定された各係数 (パラメータ)の事後分布からサンプリングした結果を示します。

特に係数3・4の推定結果が顕著ですが、事前分布を正規分布に設定した場合と比較して、推定値が0に集中していることが見受けられます。
また、分布が定まっていない場合には、確率が最も高い、確率が60%以上のように高い確率である推定値を採択する方法を検討しても良いと思います。

おわりに

本記事では手段 (分析手法)に着目していますが、どれほど有用に思える手段から導出された結果だとしも、意思決定者に納得いただくことが先ずは重要だと考えています。
高度な手段や推定精度の向上を重視することは時に分析者のエゴであり、シンプルな手段スピーディーある程度の推定精度が出ており分析結果に自然な説明が付くことが、納得感のために重要であることは多々あります。
一方で納得感すらさらに先の目的を達成するための1手段でもあるため、総じて手段専攻になりすぎず、目的や障壁などを鑑みた手段を選定できる分析チームでありたい想いです。

参考資料

より深い理解を求める場合には例えばMahlet G. Tadesse, Marina Vannucci (2022). Handbook of Bayesian Variable Selection. Chapman & Hall/CRCが参考になるかと思います。

AIエージェントで加速するBPO──ビジネスプロセスをどう変革するか

この記事は ノバセル Advent Calendar 24日目です。
こんにちは。ノバセルにてエンジニアをしております、浅田健太朗です。

この記事はこんな方向けです。

  • AIエージェントについて興味がある人
  • AIエージェントを使って業務をAX(AIトランスフォーメーション)したい人

はじめに

現代のビジネス環境はますます複雑化し、変化のスピードも加速しています。こうした状況下では、企業が迅速かつ的確に意思決定を行うことが不可欠です。近年注目を集めるAIエージェントは、この課題に対応できる有力なソリューションとして期待されています。

AIエージェントの最大の特徴は、人間のように「観察し、記憶し、計画を立て、行動する」能力を備えていることです。この柔軟な特性によって、従来のシステムでは対応が難しかった複雑なタスクや動的に変化する環境にも適応しやすくなります。結果として、業務プロセスの最適化やサービス品質の向上など、多様な領域で革新的な成果が期待されているのです。

本記事では、まずAIエージェントを構成する主要技術とアーキテクチャを解説したうえで、具体的にどのような業務領域で活かせるのか、特にBPO(ビジネスプロセスアウトソーシング)の分野を例に挙げながらご紹介します。


AIエージェントの構造と機能

AIエージェントは、大規模言語モデル(LLM)を核とし、下記の4つの主要モジュールによって構成されます。

AIエージェントの4つの構成要素

引用: A Survey on Large Language Model based Autonomous Agents

  1. 個性(Profile)

    • エージェントの属性や性格、社会的立場などを定義するモジュールです。この設定によって、エージェントの意思決定や行動パターンが変化します。
    • たとえば、マーケティング担当エージェントに「大胆かつリスクテイキングな個性」を付与すると、新商品のPRでは斬新なデザインや刺激的なキャッチコピーなど、攻めの施策を打ち出す傾向が強まります。一方、「堅実で信頼重視の個性」を持つエージェントなら、既存顧客へのアップセルや綿密な定量分析をベースにしたキャンペーン設計を重視するでしょう。
    • このモジュールは、後述する記憶・計画・行動と連携し、エージェント全体としての整合性を保ちます。
  2. 記憶(Memory)

    • エージェントの過去の行動や観察結果を蓄積するモジュールです。短期・長期の両面で情報をストックし、将来の意思決定に生かします。
    • 単にデータを蓄えるだけではなく、履歴を分析・統合することで高度な洞察を導き出します。たとえば、過去のキャンペーンで好成績を収めた要因を学習し、次回の戦略立案時にその知見を適用します。
    • 記憶モジュールによって、エージェントは自発的に学習と修正を繰り返し、変化の激しい環境でも適切な行動を取り続けることができます。
  3. 計画(Planning)

    • 設定された長期・短期目標を達成するため、具体的なステップを策定するモジュールです。
    • たとえば、新商品の市場投入を想定したシミュレーションでは、消費者の反応を予測し、最適な価格戦略や広告施策を選び出して計画を立案します。
    • 計画はリアルタイムの状況変化を考慮し、必要に応じてアップデートされます。これにより、柔軟かつ動的なプロジェクト遂行が可能になります。
  4. 行動(Action)

    • 計画モジュールで立案されたステップを具体的に実行するモジュールです。外部APIの呼び出し、ツール操作、データベースとのやり取りなどを担います。
    • 実行結果は記憶モジュールに再度蓄積され、次のアクションや計画修正に反映されます。
    • このモジュールを通じて、エージェントは効率的かつ適応的に実務をこなすことができるようになります。

これら4つのモジュールが相互に連携することで、AIエージェントは一貫性を保ちながら高度なタスクを実行し、かつ変化への柔軟な対応を可能にしています。


BPO分野におけるAIエージェントの応用

近年、日本をはじめとする多くの国で構造的な人手不足が深刻化しています。企業が持続的に成長を目指すうえでは、限られた人材リソースをいかに効率的に活用するかが重要な課題となりました。
そこで注目されるのが、専門領域のアウトソーシングを通じて生産性向上を図るBPO(ビジネスプロセスアウトソーシング)です。コア業務にリソースを集中させながらも、間接部門のプロセスを外部化し、多様な知見やスキルを活用できるメリットがあります。
一方で、BPOでは業務内容が複雑化しやすく、委託先との情報共有や品質管理が課題となりやすいのも事実です。こうした課題を解決し、さらにBPOの可能性を広げる存在として、「AIエージェント」が注目されています。

以下では、前述したAIエージェントの特性をどのようにBPOに生かせるのかを見ていきましょう。

業務プロセスの最適化シミュレーション

AIエージェントを活用すると、プロセスの最適化や事前シミュレーションを容易に行えます。これにより、現場でのボトルネックを洗い出し、改善策をスピーディに検討できるようになります。

  • 複数のAIエージェント同士を“仮想の担当者”とみなし、タスクの割り振りや進捗状況を共有・議論させることで、リアルタイムのプロジェクト管理ツールと連携しながらリソース配分やスケジュール調整が可視化されます。
  • 異なるワークフローやアウトソーシング先を組み合わせた場合の生産性やコスト効果を事前にシミュレートし、最適なパートナー選定の判断にも役立ちます。

実際、複数のAIエージェントを活用してシミュレーションを行う「Generative Agents」のような研究も進んでおり、今後は人間主体のシミュレーションに代わってAIエージェントが主役となる可能性が高いと考えられます。これが実現すれば、BPOにおけるプロセス改善のスピードと精度は飛躍的に高まるでしょう。

arxiv.org
ai-scholar.tech

サービス品質の向上

AIエージェントを導入することで、サービス品質のさらなる向上も見込めます。

  • カスタマーサポート向けのエージェントを導入すれば、問い合わせ対応のスピードや正確性を自動で評価し、その結果をもとにトレーニングやマニュアル改善を提案できます。人間のサポート担当者と協働することで、顧客満足度を高い水準で保つことが可能です。
  • データ処理業務においては、エージェントが入力から検証までをリアルタイムでモニタリング・最適化し、エラー率や処理コストを大幅に削減できます。これらのフィードバックは記憶モジュールに蓄積され、以後のプロセス改善に活かされます。

このように、AIエージェントはBPOにおける繰り返しが多く煩雑な業務を効率化するだけでなく、継続的に品質を高める仕組みづくりにも貢献します。前述した4つのモジュール(個性・記憶・計画・行動)が連動することで、複雑な業務状況にも対応し、成果を最大化する革新的なソリューションを提供できるのです。


最後に

AIエージェントは、BPOをはじめとする多様な分野で効率性と革新性をもたらす技術として注目を集めています。生成AIの進化と、先述した4つのモジュールを組み合わせることで、人間のような柔軟性と適応力を持ったシステムを構築できる点が最大の魅力です。

これらの技術を真に活用するためには、以下のポイントが重要になります。

  • モジュールの最適化
    • 個性・記憶・計画・行動を連動させ、全体として最大のパフォーマンスを引き出す仕組みづくり。
  • バイアスの考慮
    • 大規模言語モデル由来のバイアスを認識し、必要な補正や監視体制を整える。
  • 性能評価と改善
    • 使い始めて終わりではなく、長期的なモニタリングと定期的なアップデートを行う。

今後、AIエージェントがBPO業務の中核を担うだけでなく、マーケティングやカスタマーサポートなど多くの領域にも展開される可能性があります。めまぐるしく変化するビジネス環境において、その革新性はますます注目を集めることでしょう。企業のAX(AIトランスフォーメーション)を加速させるカギとして、AIエージェントがどのような未来を切り拓いていくのか、今後も目が離せません。

【Python】PuLPで始める数理最適化

この記事は ノバセル Advent Calendar 23日目です。

こんにちは。 ノバセルにてデータサイエンティストをしています、石川ナディーム(@nadeemishikawa)です。 数理最適化とは、制約条件のもとで目的関数を最大化または最小化する手法です。ビジネス上のさまざまな課題(生産計画、輸送計画、プライシングなど)や、機械学習モデルのハイパーパラメータ調整など、幅広い分野で用いられています。 Pythonで、数理最適化を扱うためのライブラリとしてオープンソースのPuLPがあります。本記事では、PuLPのインストール方法から、簡単な例としてナップサック問題を解く一連の流れをサクッと解説します。

PuLPとは

PuLPは、Pythonで簡単に使える数理最適化問題を解くPythonライブラリです。 Pythonコード内で問題の変数や制約、目的関数をシンプルに定義でき、最適化問題を解くことができます。PuLPの登場により、数理最適化を手軽に試せるようになり、さまざまな分野で利用されています。

PuLPのインストール

PuLPpip installで簡単にインストールできます。

pip install pulp

インストール後、Python環境で以下を実行して問題なくimportできれば準備完了です。

import pulp
print(pulp.__version__)

ナップサック問題を用いた基本的な使い方の説明

ここからは、PuLPを使った問題定式化から数理最適化までの流れを「ナップサック問題」を例にサクッと紹介します。 ナップサック問題とは、与えられたアイテム(各アイテムには価値と重量がある)から、ナップサックの容量上限を超えないようにアイテムを選択し、その総価値を最大化する問題です。

問題設定概要

  • ナップサック容量:W = 20
  • アイテム:以下の4品
    • アイテムA:価値15、重量5『最大1つまで』
    • アイテムB:価値7、 重量4
    • アイテムC:価値12、重量6
    • アイテムD:価値1、 重量1

モデル作成

変数の定義

アイテムごとに選択する個数を表す変数を定義します。 以降の項目の変数はそれぞれのアイテムの個数を表します。

目的関数の定義

全ての選んだアイテムの総価値を最大化します。

 

制約条件の定義

  • ナップサックの容量が20を超えることはできません。

  • アイテムAは最大1つまでしか選べません。

 
 

変数領域の定義

全ての変数は非負整数です。

 

サンプルコード解説

Step 1: 数理最適化モデルの定義

ここでは、PuLPを用いて数理モデルを定義します。

第一引数には任意の名前を文字列で渡します。ここではKnapsackProblemという名前を付けています。 第二引数では、pulp.LpMaximizeまたはpulp.LpMinimizeを指定して、問題が最大化問題か最小化問題か指定します。ここでは、ナップサックの総価値をできるだけ「大きく」したいのでpulp.LpMaximizeを選びます。

import pulp

# 問題の種類を最大化問題として定義
problem = pulp.LpProblem("KnapsackProblem", pulp.LpMaximize)

Step 2 : 変数の定義

ここでは、「アイテムAを何個」「アイテムBを何個」... のような変数を定義します。各変数は非負整数で、アイテムの個数を表します。 pulp.LpVariable()は、最適化問題で用いる変数を生成します。

第一引数は変数名(文字列)。 lowBoundは変数の下限値を指定。 upBoundは変数の上限値を指定。 catは変数の型を指定できます。pulp.LpIntegerは整数型、pulp.LpContinuousは連続値、pulp.LpBinaryは2値変数など。

アイテムAに関しては、最大1つまでという制約があるので upBound=1としています。一方、他のアイテムB, C, Dは上限を設けず、必要なら何個でも選べるようにしています。

# 各アイテムの変数を作成
x_A = pulp.LpVariable("A", lowBound=0, upBound=1, cat=pulp.LpInteger)  # 最大1つまで
x_B = pulp.LpVariable("B", lowBound=0, cat=pulp.LpInteger)
x_C = pulp.LpVariable("C", lowBound=0, cat=pulp.LpInteger)
x_D = pulp.LpVariable("D", lowBound=0, cat=pulp.LpInteger)

Step 3: 目的関数の定義

problem += ... は、ここで定義する目的関数や制約を問題インスタンスに追加することを意味します。 ここでは、ナップサックに入れるアイテムによる「価値」の合計を最大化したいので、目的関数は「(アイテムAの選択数×Aの価値) + (アイテムBの選択数×Bの価値) + ...」となります。

目的関数はpulp.LpProblemインスタンス(ここではproblem)に対して1回だけ指定します。

# 選択されたアイテムの総価値を最大化する
problem += 15 * x_A + 7 * x_B + 12 * x_C + 1 * x_D

Step 4: 制約条件の定義

最大価値を得たいといっても、以下の制約を考慮しなければいけません、

  • 「選んだアイテムの重量の合計が20を超えない」という容量制約

  • 「アイテムAは最大1つまで」という制約

problem += **制約式** の形で制約を追加します。制約式は不等式または等式(<=, >=, ==)で表します。

Step2で既にx_AupBound=1で「Aは最大1個」とはしていますが、以下のように記述することもできます。(ここではupBoundで指定したので厳密には不要ですが、例として記載。)

# 総重量がナップサックの容量を超えないように制約を追加
problem += 5 * x_A + 4 * x_B + 6 * x_C + 1 * x_D <= 20

# アイテムAは最大1つまで(今回はStep2で制約を追加済なため不要)
problem += x_A <= 1

Step 5: 最適化実行

problem.solve()で、定義した数理モデルを解きます。

# 最適化の実行
problem.solve()

Step 6: 解の表示

pulp.LpStatus[problem.status]で、最適化結果のステータス(Optimal, Infeasible, Unboundedなど)を表示できます。 pulp.value(x_A)のようにpulp.value()を使うことで、解(変数の値)を取得できます。 pulp.value(problem.objective)で最終的な目的関数の値(ここでは価値の合計)を取得できます。

# 最適化の結果を表示
print("Status:", pulp.LpStatus[problem.status])
print("Selected items:")
print(f"  A: {pulp.value(x_A)} 個")
print(f"  B: {pulp.value(x_B)} 個")
print(f"  C: {pulp.value(x_C)} 個")
print(f"  D: {pulp.value(x_D)} 個")
print("Total Value:", pulp.value(problem.objective))

出力結果:

Status: Optimal
Selected items:
  A: 1.0 個
  B: 0.0 個
  C: 2.0 個
  D: 3.0 個
Total Value: 42.0

ここから、「アイテムAを1個、アイテムCを2個、アイテムDを3個選ぶと、総価値は42で最大となる」ということが分かります。

コード全体

以下に全コードを掲載します。

import pulp

# Step 1: 数理モデルの定義
problem = pulp.LpProblem("KnapsackProblem", pulp.LpMaximize)

# Step 2 : 変数の定義
x_A = pulp.LpVariable("A", lowBound=0, upBound=1, cat=pulp.LpInteger)
x_B = pulp.LpVariable("B", lowBound=0, cat=pulp.LpInteger)
x_C = pulp.LpVariable("C", lowBound=0, cat=pulp.LpInteger)
x_D = pulp.LpVariable("D", lowBound=0, cat=pulp.LpInteger)

# Step 3: 目的関数の定義
problem += 15 * x_A + 7 * x_B + 12 * x_C + 1 * x_D

# Step 4: 制約条件の定義
problem += 5 * x_A + 4 * x_B + 6 * x_C + 1 * x_D <= 20
problem += x_A <= 1

# Step 5: 最適化実行
problem.solve()

# Step 6: 解の表示
print("Status:", pulp.LpStatus[problem.status])
print("Selected items:")
print(f"  A: {pulp.value(x_A)} 個")
print(f"  B: {pulp.value(x_B)} 個")
print(f"  C: {pulp.value(x_C)} 個")
print(f"  D: {pulp.value(x_D)} 個")
print("Total Value:", pulp.value(problem.objective))

まとめ

本記事では、PuLPを用いたナップサック問題の解法についての入門的な内容を紹介しました。実際に実務で数理最適化を用いる際は、事業への圧倒的解像度、ステークホルダーとの会話や適切な問題設定が鍵となり、難易度は高いです。しかし、こうした数理最適化問題に取り組むことで得られる思考法は、数理最適化問題に限らず、日々の問題解決能力を高めるうえでも有益なものとなると感じています。 PuLPは、今回のような単純なナップサック問題に限らず、複数のマーケティング施策の予算最適化やクーポン配布による利益最大化等、さまざまな数理最適化問題に応用可能です。この記事を足掛かりに、最適化問題へのアプローチをぜひ深めてみてください。

新卒1年目がペアプロをやってみて感じたこと

こんにちは。ノバセルでエンジニアをしている新開です。 新卒エンジニアとしてノバセルに入社してから数ヶ月。 ペアプログラミング(以下、ペアプロ)を通じて得られた学びや発見は非常に内容が濃いと感じています。 本記事では、ノバセルで行っている具体的なプラクティスやペアプロを実践する中で感じた恩恵について共有します。

この記事は ノバセル Advent Calendar 22日目です。

ペアプロとは?

アジャイルソフトウェア開発において広く採用されている手法の一つで、2人のプログラマーが1台のコンピュータを共有して共同でプログラムを作成します。 この手法は、ケント・ベック氏らが提唱した「エクストリーム・プログラミング(XP)」のコアプラクティスの一つとして知られています。

XPは改善と学習を繰り返しながら進化し続けることを目指しています。XPは柔軟で迅速な対応を重視しつつ、継続的な技術成長に主眼をおいたアジャイル開発手法の一つです。

引用: アジャイル開発におけるエクストリームプログラミング(XP)とは? | - Qiita Team 社内向け情報共有サービス

ペアプロでは次の2つの役割を持つことが一般的です。

  1. ドライバー (Driver): キーボードとマウスを操作し、コードを実際に書きます。
  2. ナビゲーター (Navigator): コードの設計やロジックを確認し、問題点や改善案を提案します。

これらの役割を一定の間隔で交代することで、双方が全体像を把握しつつ、実装とレビューを同時に進めることが可能になります。 このリアルタイムの協働作業により、コードの品質向上やスキル共有、チームの一体感の向上といった多くのメリットが得られるとされています。

プラクティス

1. コミュニケーション

ペアプロ中は常にコミュニケーションを取り続けます。 ペア内でいま考えていることなどの情報共有をリアルタイムに行うことで、誤解やミスが減り効率的に作業を進めることができます。

2. シンプリシティ

常にシンプルさを追求し、議論することは本当に重要な問題だけにします。 設計・議論をできるだけシンプルにすることで問題の本質に集中できます。

3. フィードバック

常に実装に対してリアルタイムにフィードバックを与え合うことで、より良いコードを作り上げることができます。 実装の過程においてその場で指摘や修正を行うため、バグなどの問題を早期に発見しコードの品質を高めることができます。

4. 勇気

ペアプログラミング中には、意見を述べる・ミスを認める・新しいアイデアを試すなど、いたるところで勇気を発揮する必要があります。 勇気を持って新しいアイデアを提案することで、斬新なアイデアや改善案が採用されるチャンスの創出に繋がります。

5. リスペクト

ペアのアイデアや、今まさに書かれたコードをリスペクトし続けることが基本です。 リスペクトの姿勢を持つことは自分とは異なる考え方やアイデアを受け入れることにつながります。 多様な視点を活用したより良いソリューションが生まれやすくなります。

6. 役割を一定の間隔で交代

ポモドーロテクニック (ポモドーロ) とは、25 分間の作業セッションに 5 分間の休憩をはさんだ時間管理戦略。 生産性アップだけでなく、作業を分割し 1 つずつ処理していけるため、精神的な疲れも減らせます。

引用: ポモドーロとは?仕事の生産性を上げる時間管理術 [2024] • Asana asana.com

ポモドーロ・テクニックに倣い25分の作業時間・5分の休憩時間を1セッションとして、セッションごとにペアの役割を交代しています。 役割を一定間隔で交代することにより両者の解像度を均等に保て、かつ集中力を持続させることが可能になります。 ペアプロは想像以上に体力を消費します。時間で区切りしっかりと休憩を取ることがポイントだと感じています。

7. ペアプロ後に反省会

マインドセットが意識できていたかを確認します。 できていなかった場合は次回できるようになるためのすべきアクションを明確にし、できていた場合は今後も再現性高く実施するために何が良かったのかを明確化します。

新卒1年目が感じた恩恵

1. コードレビューがリアルタイムに行える

通常のコードレビューではPull Requestを出した後にコメント/Approveを受け取る形式が一般的ですが、ペアプロではその場で即座にフィードバックを得ることができます。 これによりミスの早期発見ができ差し戻しで発生するタイムロスが減少しました。

2. スキルアップ

リアルタイムのフィードバックを通じて自身のコードスタイルの改善点に気づける機会が増えます。 また相手の視点や知識を吸収することでエンジニアとしてのスキルアップに限らず思考プロセスの幅が広くなります。

3. チーム内の信頼関係の構築

ミスを認めたり不明点を尋ねる姿勢は、チームメンバーからの信頼を得るきっかけになると考えています。 このような態度はオープンで協力的なチーム文化を育みます。

さいごに

最後にエンジニア歴10年以上の先輩に新卒1年目とのペアプロでどのようなことに意識しているかを聞いてみました。

私は経験が少なめのエンジニアとペアプロするときに2つのことを意識するようにしています。
1つ目は、自分の役割がナビゲーターの時は改善点を指示しすぎないようにすることです。問いを投げかけることで自発的に思考をして問題に気づくことができると考えています。
2つ目は、自分の役割がドライバーの時に1人で進めすぎないようにすることです。相手を置いていかないことで両者が持続的に生産性を発揮できるようになります。

ペアプロは新卒1年目のエンジニアにとって、学びと成長の機会を大きく広げてくれる手法だと感じました。 最初は緊張や戸惑いもありましたが、実践を重ねるごとにスムーズに進められるようになり、その恩恵を強く実感しました。 これからもチームでの学びを大切にしながら、開発効率を最大にできるように尽力していきます。