📚 背景知識(読んでから問題へ)
| Day | テーマ | 出した答え |
|---|---|---|
| 141 | 最終提出2枠の選び方 | Public LBの見た目ではなく、CVスコアを信じて選ぶべき |
| 142 | 探索と活用のトレードオフ | CVが伸び悩んだら、一定の確率で当たる「探索」に賭ける価値がある |
| 143 | チームマージの意思決定 | 実力差より相関の低さ(多様性)が価値を生む。ブレンドの質が最重要 |
| 144 | メダル圏内までの距離の見積もり | シェイクアップとカットオフラインの変動を組み込んで逆算する |
P(beat_solo)など)を使っていた。実際の意思決定には「複数の戦略の選択肢を、同じ最終評価指標(今日ならGold圏内到達確率)で横並びに比較すること」が必要である。今日はDay142の探索メカニズム・Day143のマージメカニズム・Day144のシェイクアップメカニズムをすべて1本のコードに統合し、4つの現実的な戦略を同一の物差しで比較する。🎯 問題
タスクA(戦略・記述)
以下3点をそれぞれ2〜3文で説明する。
P(medal)が高かった戦略とそうでなかった戦略の差を踏まえ、「探索」と「マージ」のうちどちらがより強い武器だったか、その理由TARGET_PROBにわずかに届かなかった場合、Day141の「CVを信じる」結論はこの状況でどう位置づけられるか(成長の一手ではなく何の役割を果たすか)タスクB(実装・シミュレーション)
| 項目 | 値 |
|---|---|
| 残り日数・現在のPublic LB | D_TOTAL=10 / PUBLIC_LB_NOW=0.803 |
| Goldカットオフ・シェイクアップ(Day144と同型) | GOLD_CUTOFF_PUBLIC_EST=0.815 / SHAKEUP_STD=0.006 |
| カットオフの上昇・目標確率 | CUTOFF_DRIFT_MEAN=0.003 / TARGET_PROB=0.70 |
| 活用(exploit)の逓減改善 | EXPLOIT_GAIN_BASE=0.0018 / EXPLOIT_DECAY=0.88 |
| 探索(Day142方式) | EXPLORE_DAYS=4 / P_BREAKTHROUGH=0.25 |
| マージ(Day143方式) | MERGE_DAY=2 / P_MERGE_FAIL=0.15 |
import numpy as np N_SIM = 20000 D_TOTAL = 10 PUBLIC_LB_NOW = 0.803 GOLD_CUTOFF_PUBLIC_EST = 0.815 SHAKEUP_STD = 0.006 CUTOFF_DRIFT_MEAN = 0.003 CUTOFF_DRIFT_STD = 0.004 TARGET_PROB = 0.70 # 活用(exploit): 逓減する改善(Day141-144と同じ構造) EXPLOIT_GAIN_BASE = 0.0018 EXPLOIT_DECAY = 0.88 # 探索(explore, Day142方式) EXPLORE_DAYS = 4 P_BREAKTHROUGH = 0.25 BREAKTHROUGH_LOW, BREAKTHROUGH_HIGH = 0.006, 0.010 MISS_GAIN = 0.0005 # チームマージ(Day143方式) MERGE_DAY = 2 INTEGRATION_DAYS = 2 PARTNER_MEAN = 0.803 PARTNER_STD = 0.015 RHO_LOW, RHO_HIGH = 0.3, 0.9 ENSEMBLE_GAIN_MAX = 0.010 TEAM_GAIN_BASE = EXPLOIT_GAIN_BASE * 1.5 P_MERGE_FAIL = 0.15
gain(base, decay, start, length)(Day142-144と同じ)を実装するexploit_only / explore_then_exploit / merge(optimal) / merge(naive))。いずれもN_SIM件の「シェイクアップ前の最終CV」を返すp_medal(own_final, rng)を実装し、全戦略に共通で適用するown_final平均・標準偏差・P(medal)を計算し、最も高い戦略を特定するEXPLORE_DAYSを0〜8で変化させP(medal)の変化を調べるMERGE_DAYを1〜8で変化させ、optimal/naive両方のP(medal)を調べるrequired_deltaを求める💡 ヒント
タスクAの1.は「Day141-144それぞれの結論は"その意思決定の中でどちらが良いか"にしか答えていない」点に気づけるかがポイント。2.と3.はタスクBの実測結果を先に出してから、数値を根拠に説明する構成になる。タスクBは、これまで別々の日に書いたコードを1つのファイルに集約し、同じp_medal関数をすべての戦略に適用する点が新しい。Day143のstrategy_mergeは「シェイクアップ前の最終CV」を返すところまでで止め、Day144のp_medalにそのまま渡せる形にすることが設計のポイントである。
strategy_exploit_onlyは乱数を使わないため、np.full(N_SIM, final)で同じ値をN_SIM件に複製し、他の戦略と同じ形式(N_SIM件の配列)で扱うと後続のp_medalを共通化できる- 戦略ごとの比較では、戦略内部の乱数を
rng=np.random.default_rng(0)、p_medal内のシェイクアップ乱数をrng2=np.random.default_rng(1)と、独立したシードで固定すると戦略間の違いだけが見やすくなる EXPLORE_DAYSやMERGE_DAYの感度分析は、対象パラメータ以外を固定して関数を呼び出し直せばよい(Day143-144と同じやり方)required_deltaの二分探索は、最良戦略のown_finalに+ deltaを加えてからp_medalに渡す形で実装する
def strategy_merge(rng, blend_mode): own_at_merge = PUBLIC_LB_NOW + gain(EXPLOIT_GAIN_BASE, EXPLOIT_DECAY, 0, MERGE_DAY) partner_score = rng.normal(PARTNER_MEAN, PARTNER_STD, N_SIM) rho = rng.uniform(RHO_LOW, RHO_HIGH, N_SIM) ensemble_bonus = ENSEMBLE_GAIN_MAX * (1 - rho) if blend_mode == "optimal": blended = np.maximum(own_at_merge, partner_score) + ensemble_bonus else: blended = (own_at_merge + partner_score) / 2 + ensemble_bonus remaining = max(D_TOTAL - MERGE_DAY - INTEGRATION_DAYS, 0) fail = rng.random(N_SIM) < P_MERGE_FAIL success_final = blended + gain(TEAM_GAIN_BASE, EXPLOIT_DECAY, 0, remaining) fail_final = own_at_merge + gain(EXPLOIT_GAIN_BASE, EXPLOIT_DECAY, MERGE_DAY, remaining) return np.where(fail, fail_final, success_final) def p_medal(own_final, rng): own_private = own_final + rng.normal(0, SHAKEUP_STD, N_SIM) cutoff_private = (GOLD_CUTOFF_PUBLIC_EST + rng.normal(CUTOFF_DRIFT_MEAN, CUTOFF_DRIFT_STD, N_SIM) + rng.normal(0, SHAKEUP_STD, N_SIM)) return (own_private > cutoff_private).mean()
✅ 模範解答
for name, fn in strategies.items(): rng = np.random.default_rng(0) own_final = fn(rng) rng2 = np.random.default_rng(1) p = p_medal(own_final, rng2) print(f"{name:24s} mean_final={own_final.mean():.5f} P(medal)={p:.3f}") # ============ 実測結果(タスクB-4) ============ # A_exploit_only mean_final=0.81382 std=0.00000 P(medal)=0.327 # B_explore_then_exploit mean_final=0.81731 std=0.00659 P(medal)=0.467 # C_merge_optimal mean_final=0.82472 std=0.00875 P(medal)=0.697 ← 最良 # D_merge_naive mean_final=0.81951 std=0.00765 P(medal)=0.545 # # best strategy = C_merge_optimal P(medal)=0.697(TARGET_PROB=0.70にわずかに届かない) # # --- 追加検証3: 最良戦略(C_merge_optimal)起点でrequired_deltaを二分探索 --- # required_delta(C_merge_optimal起点) = 0.00010
📊 結果の可視化
| 戦略 | mean_final | std | P(medal) |
|---|---|---|---|
| A_exploit_only | 0.81382 | 0.00000 | 0.327 |
| B_explore_then_exploit | 0.81731 | 0.00659 | 0.467 |
| C_merge_optimal | 0.82472 | 0.00875 | 0.697(最良) |
| D_merge_naive | 0.81951 | 0.00765 | 0.545 |
🪜 Step-by-Step 解説
1なぜ4つの戦略を「同じp_medal関数」に通す設計にするのか
strategies = {
"A_exploit_only": strategy_exploit_only,
"B_explore_then_exploit": strategy_explore_then_exploit,
"C_merge_optimal": lambda rng: strategy_merge(rng, "optimal"),
"D_merge_naive": lambda rng: strategy_merge(rng, "naive"),
}
P(beat_solo)、required_deltaなど)を使っていた。すべての戦略が返す「シェイクアップ前の最終CV(own_final)」という共通の中間形式を経由し、同じp_medal関数に通すことで、初めて4つの戦略を同一の物差し(P(medal))で横並びに比較できる。この「複数の意思決定ロジックの出口を1つの共通形式に揃える」設計は、実務の意思決定システムでも頻出する考え方である。2なぜB(探索して活用)はC(マージ×最適)に及ばないのか
# B_explore_then_exploit P(medal)=0.467
# C_merge_optimal P(medal)=0.697
Uniform(0.006, 0.010)の改善が得られるが、外れればMISS_GAIN=0.0005とほぼ横ばいになる「上振れのみ」の賭けである。一方Cのマージ(optimal)はblended = max(own_at_merge, partner_score) + ensemble_bonusという式により、パートナーがどれだけ弱くても自分の実力を下回らない上に、相関が1未満である限り正の多様性ボーナスが上乗せされる。探索が「上振れ狙い」であるのに対し、マージ(optimal)は「下振れを防ぎながら上振れも取りにいく」非対称に有利な設計になっている。3なぜ最良の戦略でもTARGET_PROBにわずかに届かないことがあるのか
# C_merge_optimal P(medal)=0.697 (TARGET_PROB=0.70)
# required_delta(C_merge_optimal起点) = 0.00010
TARGET_PROB=0.70はあらかじめ決めた目標値であり、用意した戦略の実力の範囲内に必ず収まる保証はない。実測では最良の戦略でも0.697と目標にわずか0.003足りなかった。ここで重要なのは「大体近いから良しとする」のではなく、Day144と同じ二分探索の手法をそのまま最良戦略に適用し、「あと具体的にどれだけの上乗せ改善(required_delta)が必要か」を数値で出すことである。今日の実測ではrequired_delta=0.00010とごくわずかであり、「最適に組み合わせれば目標まであと一押し」という具体的で行動可能な結論が得られる。🔁 追加検証(EXPLORE_DAYS・MERGE_DAYを変化させた場合)
# --- EXPLORE_DAYSを変えた場合(B_explore_then_exploit) ---
# EXPLORE_DAYS=0 mean_final=0.81382 P(medal)=0.327 (=exploit_onlyと同じ)
# EXPLORE_DAYS=2 mean_final=0.81515 P(medal)=0.388
# EXPLORE_DAYS=4 mean_final=0.81731 P(medal)=0.467 ← 今日のメイン設定
# EXPLORE_DAYS=6 mean_final=0.82003 P(medal)=0.557
# EXPLORE_DAYS=8 mean_final=0.82319 P(medal)=0.645
# --- MERGE_DAYを変えた場合 ---
# MERGE_DAY=1 mode=optimal mean_final=0.82502 P(medal)=0.698
# MERGE_DAY=1 mode=naive mean_final=0.81991 P(medal)=0.559
# MERGE_DAY=2 mode=optimal mean_final=0.82472 P(medal)=0.697 ← 今日のメイン設定
# MERGE_DAY=2 mode=naive mean_final=0.81951 P(medal)=0.545
# MERGE_DAY=4 mode=optimal mean_final=0.82352 P(medal)=0.671
# MERGE_DAY=4 mode=naive mean_final=0.81804 P(medal)=0.497
# MERGE_DAY=6 mode=optimal mean_final=0.82135 P(medal)=0.603
# MERGE_DAY=6 mode=naive mean_final=0.81556 P(medal)=0.414
# MERGE_DAY=8 mode=optimal mean_final=0.81800 P(medal)=0.480
# MERGE_DAY=8 mode=naive mean_final=0.81192 P(medal)=0.301
🧮 数学・統計の補足(文系向け)
旅行の計画を立てるとき、「交通手段は新幹線が飛行機より快適」「ホテルはA館がB館より部屋が広い」というように、個々の要素を単独で比較しても、「結局この旅行プラン全体でいくらかかって、何日で行けるのか」は分かりません。旅行プラン全体を比較するには、「総費用」「総所要時間」という共通の物差しで、複数の組み合わせ(新幹線+A館、飛行機+B館、…)を横並びに評価する必要があります。今日のシミュレーションで4つの戦略すべてを
P(medal)という同じ指標に通したのは、まさにこの「共通の物差しでプラン全体を比較する」という考え方です。
探索(当たれば大きいが外れてもほぼ横ばい)とマージ(optimal, 下振れを防ぎながら上振れも狙う)の違いは、「宝くじを買う」と「損害保険付きの投資をする」の違いに似ています。宝くじは当たれば大きいですが、外れれば掛け金がほぼ戻りません。一方、
max(own_at_merge, partner_score)という式は、「パートナーが弱くても自分の実力は失わない」という保険がかかった上で、「相性が良ければボーナスも得られる」投資に近い構造です。同じ「不確実な相手に賭ける」行為でも、下振れの設計次第で全く違うリスク・リターンになることが今日の実測で数値として現れています。
🏆 Kaggleでの実践的な使い方
よく使われるコンペカテゴリ: ☑ 表形式データ(Tabular) / ☑ 自然言語処理(NLP) / ☑ 画像認識(CV) / ☑ 時系列(Time Series)
🧩 意思決定の「出口」を揃えたミニシミュレーターを持つ
共通形式で出力する小さな関数群
探索・マージ・提出戦略それぞれの選択肢を「シェイクアップ前の最終CV」という共通形式で出力する関数群を用意しておくと、コンペ終盤で状況が変わるたびにp_medalに通すだけで最新の判断材料が得られる。
📉 「届かない」結果を隠さず直視する
required_deltaに変換して行動計画へ
今日の実測のように、最も良い戦略を選んでもなお目標確率にわずかに届かないことは現実にも起こる。その場合は具体的な追加目標(required_delta)に変換し、残りの日数で何をすべきかの行動計画に落とし込む。
♻️ 過去の検証ロジックはパーツとして再利用する
使い捨てにしない
探索の当たり外れ、マージの成功/失敗、シェイクアップのノイズなど過去に検証したロジックを関数として再利用可能な形にしておくと、新しいコンペでも同じ枠組みを素早く組み立てられる。
⚠️ よくある誤解・ミス
| 誤解・ミス | なぜ起こるか | 正しい理解 |
|---|---|---|
| 個別の意思決定をそれぞれ最適化すれば、全体としても最良になると思い込む | 「部分が良ければ全体も良い」という直感的な単純化 | 今日の実測では、4つの戦略を同じP(medal)という物差しで比較して初めてC_merge_optimal(0.697)が最有力だと分かった。個別の評価軸のままでは戦略同士を直接比較できない |
| 探索はマージよりリスクが高く、避けるべきだと一律に考える | 「知らない相手・知らない結果」への漠然とした不安 | 今日の実測では確かに探索(B, 0.467)はマージ(C, 0.697)に劣ったが、これは今日のパラメータ設定に依存する結果であり、常にマージが優れているとは限らない |
| 最良の戦略を選べば必ず目標確率に届くと思う | 「最善を尽くせば目標は達成される」という願望的思考 | 今日の実測では最良のC_merge_optimalでもP(medal)=0.697とTARGET_PROB=0.70にわずかに届かなかった。届かない場合はrequired_deltaで「あとどれだけ必要か」を数値化することが次の一手につながる |
| マージのタイミングは早ければ早いほど際限なく良いと思う | Day143の「早めマージが望ましい」を単純に延長してしまう | 今日の追加検証ではMERGE_DAY=1(0.698)とMERGE_DAY=2(0.697)の差はごくわずかであり、直線的に良くなるわけではない。統合後の残り日数の下限を確保できていれば効果は頭打ちになる |
🚀 次のステップ
- 発展: 今日は4つの戦略を独立に評価したが、実際には「探索してからマージする」「マージしてから残り日数でさらに探索する」といった戦略の組み合わせも可能である。
strategy_mergeのsuccess_finalの中にBの探索メカニズムを組み込んだハイブリッド戦略を実装し、P(medal)がさらに改善するか試してみましょう。また今日はP_MERGE_FAIL=0.15を固定したが、パートナー候補が複数いる場合に「並行して複数人に声をかける」ことで実効的な失敗確率が下がる効果も検証する価値があります - 次回予告: Phase6の詳細テーマリスト(1-20、SOTA手法追跡→カスタムアーキテクチャ→高度なアンサンブル→コンペ戦略)を本日で完了しました。roadmap.mdに記載されたPhase6の主要テーマのうち、まだ扱っていない「解法公開・フォーラム — Discussionで上位ソリューションを学ぶ」に次回から取り組む予定です
Phase 6 の学習マップ(全20テーマ・本日で完了)
Day141で最終提出の選び方、Day142で探索/活用トレードオフ、Day143でチームマージ、Day144でメダル圏内までの距離の見積もり、Day145でこれら4つを統合して比較した。最良の戦略(早期マージ×最適ブレンド)でもGold到達確率は69.7%と目標の70%にわずかに届かず、あと0.0001程度の上乗せが必要という結論で、Phase6の詳細テーマ表を締めくくった。
📝 自己評価(解いた後に記入)
自分の回答・気づき・メモ: