TT Lab
はじめる
学ぶ 学習パス コース

デバッグ実戦

動く顧客と動かない顧客 — 差分表で候補を消す

TT Labで続きを見る

目標

成功サンプルと失敗サンプルを属性ごとに分けて差分表を作り、すべての失敗にあって、どの成功にもない値だけを候補に残します。完全に相関している偽の候補を、新しいサンプルと介入実験でそれぞれ外し、1つの属性では分かれない相互作用まで見つけ出します。

なぜ重要なのか

「ある顧客は動いて、ある顧客は動きません」は、悪い知らせのように聞こえますが、実は良い知らせです。動く側があるということは、対照群があるということです。失敗のログだけを掘ると、すべての行が怪しく見えますが、成功のログにも同じ行があるなら、それは原因ではなく背景です。 このラボで難しいのは、表を作るコードではなく、候補が2つ残ったときに何をするかです。同じ日にデプロイされた2つのものが常に一緒にいると、サンプルだけでは区別できません。このとき、もっともらしいほうを選んで報告すると、半分の確率で何日も無駄にします。 分ける道は2つだけです。2つが分かれるサンプルをさらに得るか、属性を1つだけ変えて残りを固定し、結果がひっくり返るかを見ることです。前者は観察で、後者は実験であり、因果を語れるのは実験だけです。 採点ツールは、あなたの結論を信じません。採点ツールが、原因と偽の候補を毎回別の位置に埋め込んだサンプルを作り、あなたのツールを実際に実行して、選び出された候補の集合を、埋め込んだ答えと照合します。

ステップ

  1. /root/diff/gen_cases.pyを作成して実行し、/root/diff/cases.json(240件)、cases2.json(120件)、cases3.json(180件)、repro.pyを作ってください。
  2. /root/diff/table.jsonに、属性ごとの値ごとに、失敗の件数と成功の件数を書いた差分表を作ってください。
  3. /root/diff/differential.pyを作成して、すべての失敗にあって、どの成功にもない値を候補として選ばせてください。
  4. /root/diff/candidates.jsonに、候補の一覧と、消した候補を根拠とともに書いてください。
  5. 新しいサンプルを合わせてもう一度実行し、/root/diff/verdict.jsonに、生き残った原因1つと、外れた候補、その根拠となったサンプル番号を書いてください。
  6. differential.pyにペア分析を加え、/root/diff/pairs.jsonにcases3.jsonのペア候補を書いてください。
  7. repro.pyで属性を1つだけ変えて、結果がひっくり返るかを確認し、/root/diff/confirm.jsonに書いてください。
  8. /root/diff/summary.jsonを作り、/root/diff/diff_report.mdに4つの節で報告してください。

参考

サンプルと再現ツールを手に入れる

/root/diff/gen_cases.pyを作成して実行し、/root/diff/cases.json(240件)と、cases2.json(120件)、cases3.json(180件)、repro.pyを作ってください。

現場で手に入れるのは結論ではなくサンプルです。このスクリプトをそのまま保存して実行すれば構いません。できたcases.jsonを少し開いて、成功と失敗がどのような形で書かれているかを見てください。

属性ごとの差分表を作る

/root/diff/table.jsonに、failures・successesとattributesを書いてください。attributesは、属性名ごとに、値別の{"fail": 건수, "ok": 건수}(プレースホルダーは件数です)を持ちます。case_idとoutcomeは属性ではありません。

表が先です。表なしで目で眺めると、「失敗に多く見える値」と「失敗にだけある値」を区別できません。属性名は、サンプルからそのまま読み取ってください。手で書くと1つ落とし、落とした属性は永遠に候補になりません。

候補を選ぶツールを作る

/root/diff/differential.pyを作成して、すべての失敗にあって、どの成功にもない속성=값(プレースホルダーは属性と値です)をcandidatesとして、すべての失敗にあるものの成功にもある値をeliminatedとして出力させてください。--casesは、複数回指定できる必要があります。

集合演算を2回行えば終わりです。失敗サンプルの共通部分を求め、成功サンプルの和集合を引きます。引き算で消えた値がeliminatedです。人が表を目で眺める代わりにこの2行を使う理由は、属性が20個になっても手順が同じだからです。

候補と消した候補を根拠とともに書く

/root/diff/candidates.jsonに、candidates(候補の一覧)とeliminated(消した候補)を書いてください。eliminatedの各項目は{"attribute": "속성=값", "reason": "…"}(プレースホルダーは属性と値です)で、reasonには、その値が現れた成功サンプルの件数が数字で入っている必要があります。

消したものを書き残す理由は、次の人が同じ道をもう一度歩かないようにするためです。「すべての失敗にtoken認証があった」という事実は、成功のいくつかにもtokenがあったという事実と並べたときだけ、意味を持ちます。その数字を表から持ってきてください。

新しいサンプルで偽の候補を外す

cases.jsonとcases2.jsonを一緒に入れてもう一度実行し、/root/diff/verdict.jsonに、cause(生き残った原因1つ)、eliminated_by_new_batch(外れた候補)、evidence_case_ids(根拠となったcases2.jsonの件番号)を書いてください。

サンプルだけでは2つを区別できなかった理由は、データに2つを分ける組み合わせがなかったからです。新しいサンプルには、その組み合わせが入っています。根拠となる件は2種類あります。外れるべき属性を持っているのに成功した件と、その属性がないのに失敗した件です。

1つの属性では分かれない場合

differential.pyに--pairsを付けてペア候補を探させ、cases3.jsonで実行して、/root/diff/pairs.jsonにsingle_candidatesとpair_candidatesを書いてください。ペアは、2つの値を含む一覧で書きます。

単独の候補が1つもないサンプルがあります。2つの値が一緒のときだけ失敗するからです。すべての失敗にある値の中から2つずつペアにして、その2つを一緒に持つ成功が1つもないペアを探してください。すでに単独で候補になっている値を含むペアは、新しい情報ではありません。

属性を1つだけ変えてひっくり返るかを見る

/root/diff/confirm.jsonに、claim(主張する原因)、base(基準の属性の組み合わせ7つ)、flipped_attribute、base_outcome、flipped_outcomeを書いてください。baseとひっくり返した組み合わせはちょうど1つの属性だけが違う必要があり、2つの結果は互いに違う必要があります。

サンプルは観察で、再現ツールは実験です。残りをすべて固定したまま、主張する属性1つだけを変えて結果がひっくり返れば、その属性は相関ではなく原因です。2つを一度に変えると、どちらがひっくり返したのかがわかりません。

消したものまで1枚で報告する

/root/diff/summary.jsonにweek1_cases・week1_candidates・cause・eliminated_by_new_batch・pair_only_tenant・interventionを書き、/root/diff/diff_report.mdに## 무엇이 갈렸나、## 무엇을 지웠나、## 상관인가 원인인가、## 남은 위험(韓国語の見出しは、順に「何が分かれたか」「何を消したか」「相関か原因か」「残るリスク」という意味です)の4つの節で報告してください。

報告書に残った候補だけを書くと、次の人が同じ道をもう一度歩きます。消した候補と消した根拠を一緒に書いてください。介入実験の2つの結果も、数字ではなく単語ですが、証拠です。