本稿について
AHC016 Graphorean の考察(主に理論面)について書いています。最尤推定( ※ 追記:あとで調べたら事前分布を仮定するものはベイズ推定と呼ぶのが正しいようです *1)に類する方法で復元をします。正規分布近似によるグラフを構築した際の誤判定率の計算方法についても記載しています。
残念ながらこれをフルに活用した解法を提出するところまでいけませんでしたが、理論面の参考になればと思います。
方針
本問は
- 構築フェイズ
- 復元フェイズ
に分けることができます。
復元フェイズについては最尤推定(後述)が理論的に最善であることが証明できます。
本稿では、厳密な最尤推定の代わりに、特徴量をいくつか用いて連続関数の対数尤度の最大化に帰着する方法を紹介します。
構築フェイズは、(復元フェイズで最尤推定を用いる前提で)期待得点の最大化をすれば良いです。グラフを選択した段階で理論的には期待得点が決まりますが、これを現実的に計算することはできるでしょうか?
実は、特徴量を表す確率変数を独立正規分布で近似すると、構築したふたつのグラフについて誤判定を起こす確率が計算できます *2 。ここから期待得点を簡易的に予測することができます。あとは焼きなまし等で期待得点が最大となるグラフのセットを構築すれば良さそうです。
実はこの方法には問題(後述)があるのですが、途中までは理論として面白いと思うので紹介します。
最尤推定
最尤推定とは
最尤推定とは、本問の例では反転・並び替え後の結果( )を見て、 から のグラフのうち、それを選んだ場合に になる条件付き確率 *3 が最大のものを選ぶ方法です *4 。
なお復元フェイズでは最尤推定による選択が理論的に最善となることが証明できます *5 。これは、(通常の最尤推定では事前分布が不明であることが多いが)本問では事前分布として から までのグラフが等確率で選ばれることが与えられているので、各グラフが正しい確率は尤度に厳密に比例することから従います。
特徴量
実際に、各グラフから条件付き確率を計算することは、グラフの頂点数 *6 がよほど小さくないと現実的でないです。このためいくつか特徴量を使って判定しました。特徴量としては以下を採用しました。
- 全体の辺の本数。
- 各頂点 を固定したときの、 と隣接する辺の本数。
- 各頂点 を固定したときの、 の組であって から 、 から 、 から のいずれにも辺が存在するものの個数
- 各頂点 を固定したときの、 の組であって から 、 から 、 から のいずれにも辺が存在しないものの個数
最初のものはスカラー、それ以外はいずれも 元ベクトルになります。
なお、グラフは 行列で表されているとして考えていた *7 *8 ので、この考え方だと例えば 2. は行ごとの 1 のマスの個数と言い換えられます。
3. と 4. は、 を含む 3 点からなるクリーク・反クリークの個数とも言い換えられます。
判定の方法
行ごとの 1 のマスの個数の遷移行列は、愚直に DP で prob(from, to) を全パターン計算できます *9。実装上はこれの対数を持っておくとよいです。
3 点クリークは実際に計算するのは難しいので、期待値と分散のみを計算することにしました。あとは中心極限定理を信じて正規分布を仮定すれば良いです。期待値は 3 点を固定して独立に計算してから合計すればよい(期待値の線形性)ので簡単です。分散は少し工夫が必要ですが、「共分散」の概念を知っていれば計算できると思います。
頂点の対応
ひとつ問題なのは、シャッフル前後でどの頂点とどの頂点が対応するかが分からないところです *10。
簡単のため、頂点ごとの特徴量をソートして、大小順にぴったり対応すると考えました。 *11 。
期待値・分散・共分散について(復習)
確率変数 および について、 を の期待値、 を の分散、 を と の共分散とします。
共分散は
で定義されます。
このとき、次の性質が成立します。
と が独立のとき
これを繰り返し使うと、多数の確率変数の和である確率変数について、それぞれの分散と任意の 2 つの共分散が分かっていれば、その合計の期待値・分散を求めることができます *12。
各特徴量の期待値・分散の計算
反転率(問題文中の eps)を 、反転しない確率を とします。
1. 全体の本数
全体の辺の本数については、最初の辺の本数を とすると
平均
分散
の二項分布に従います。計算上は正規分布に近似します *13 。
2. 各頂点から出ている辺の本数
各頂点から出ている辺の本数は、最初の該当の本数を とすると
平均
分散
です。
これも二項分布に従うので正規分布で近似できそうですが、少し気になる点があります。それは各頂点から出ている辺の本数を全部合計すると、辺を 2 回ずつカウントしていることになるため、独立性が担保されなくなります。
全く同じものを 2 回合計すると平均は 2 倍、分散は 4 倍になるので、分散を最大 2 倍ぐらい過小評価している可能性があります *14 。
3. 各頂点を含む 3 点クリークの個数
各頂点( とする)に隣接する 3 点クリークの個数は、3 辺の組ごとに遷移確率が次の表で定まります。期待値はここから直接計算できます。
from\to | 0 | 1 | 2 | 3 |
---|---|---|---|---|
0 | q^3 | 3p*q^2 | 3p^2*q | p^3 |
1 | p*q^2 | q^3 + 2p^2*q | 2p*q^2 + p^3 | p^2*q |
2 | p^2*q | 2p*q^2 + p^3 | q^3 + 2p^2*q | p*q^2 |
3 | p^3 | 3p^2*q | 3p*q^2 | q^3 |
分散はちょっとややこしいですが、共分散の考え方を使うと計算できます。つまり、 3 頂点の組すべてについて期待値と分散が求まっていて、 2 つの「3 頂点の組」に対して共分散が求まっていれば全体の期待値と分散が求まります。
分散については、 の組が 3 点クリークになる場合に 1 、それ以外の場合に 0 を取る確率変数を とすると、 なので上の表から求まります。
頂点 を固定するとき、 の組と の組は相関がないので共分散はゼロです *15 。 と の組については 間の辺が共通なので相関があります。
上の公式に当てはめて頑張って計算すると共分散を求めることができます。
例えば、 の 4 点について、任意の 2 点間に最初辺があるとして、
の組が 3 点クリークになる場合に 1 、それ以外の場合に 0 を取る確率変数 と の組が 3 点クリークになる場合に 1 、それ以外の場合に 0 を取る確率変数 の共分散 を求めてみます。上の定義を思い出すと
と計算できます。
なお、上記の および
の組が 3 点クリークになる場合に 1 、それ以外の場合に 0 を取る確率変数
について、 をまとめて考えると考察・実装がラクになります。
結果を言ってしまうと、この結果は 間の 6 個の候補にある辺の本数と場所によって、次のように決まります。
6 本の辺がある場合:
5 本の辺がある場合:
4 本の辺がある場合で、それらがサイズ 4 のループをなす場合:
4 本の辺がある場合で、それらのうち 3 つがループをなす場合:
3 本の辺がある場合で、それらが直線状に並んでいる場合:
3 本の辺がある場合で、それらが長さ 3 のループをなすまたは 1 点から 3 本出ている場合:
2 本の辺がある場合で、それらがつながっている場合:
2 本の辺がある場合で、それらが離れている場合:
1 本の辺がある場合:
0 本の辺がある場合:
反クリークについても同様です。
計算量が気になるかもしれませんが、グラフ盤面を予め固定しておけばパラメトリックな方法で で計算できる場合もあります。受け取ったグラフのカウントは bit 演算でグラフごとに などでできるので十分高速です。
盤面候補の選出
いくつか候補を出して、なるべくお互いが「近くならない」(誤判定する確率が低い)ように選びたいです。
下記の 4 パターンを使いました。
Type 0(左上):一部のノードのみ全結合 *16
Type 1(左下):Type 0 の逆 *17
Type 2(右上):差が一定以内のものを結合 *18
Type 3(右下):3 段タイプ *19
誤判定率
最尤推定による判定では、各初期グラフ について各特徴量 による尤度の積を計算して、その合計が最大となる を選ぶという方法でした。
ここではすべての分布を正規分布で近似して、対数尤度の和の最大化と考えます。正規分布の確率密度関数は で表されることを思い出しましょう。
平均 、分散 の正規分布を で表します。確率変数 がこの分布に従うことを のように書きます。
各特徴量 の分布を とすると、 における対数尤度は で表されます。復元フェイズではこの和が最大の を選ぶのが最善です。
次にこれが誤判定を起こす確率を計算 *20 します。
誤判定をするというのは 番目のグラフについて、 番目のグラフの特徴量に基づく対数尤度の合計よりもあるほかのグラフ( とします)の特徴量に基づく対数尤度の合計の方が大きくなることです。まず と を固定して、 を であると誤判定する確率を計算します。
グラフ の 番目の特徴量の確率変数を とすると、次の式が成立する確率を求めれば良いです。
右辺はパラメータが ではなく に基づいていますが、確率変数は に基づく であることに注意してください。
ここで とおくと、これは標準正規分布に従う( )ので、 が成立します。
これを使って上式をさらに変形すると
よってこの左辺を とおくと、この期待値 と分散 は
と計算できます。これも正規分布だと思うと、求める誤判定率は (ただし は正規分布の累積分布関数)となります。
問題点
紹介した方法にはいくつか問題点があります。
実験してみると 1. と 2. の問題はあまり大きくないことが分かります。一方、条件によっては 3. の問題がかなり大きいようです。実際、場合によっては本稿の方法で計算した誤判定率がかなり小さい *21 場合でも、正規分布を仮定して実験するとほとんどの場合で誤判定をする *22 こともありました。順序統計量(ソート後の確率変数)が満たす性質に近い分布を選びがちになる場合があるということかなと思います。
ソートして使う以外の方法としては、「〇〇以下である特徴量の個数」のような確率変数を新たに特徴量とすれば、これはソートによる影響を受けないのでもう少し良い判定ができそうです *23 。
参加記
実はコンテスト中、一瞬 5 位ぐらいまでは上がってその時点では解法ガチャに成功したかと思っていました(この時点では最尤推定ぐらいしかしていません。しかもいろいろミスってました)。
5 位!#AHC016 pic.twitter.com/7q3yRKwBdc
— きり (@kiri8128) November 13, 2022
その後、誤判定率の推定、それによる焼きなまし法、順序統計量による期待値・分散の補正などいろんなアイデアを思いついて試しましたがことごとく悪くなるという結果になってしまいました *24 。
ソートによるノイズが大きいことに気付いたのが最終日で、それ以降はちょっと時間的に何もできないという結果でした。
結果的に、 5 位時点のコードほぼそのままみたいなものが最終提出になりました *25 。
誤判定率については、正規分布に従う乱数で数回試すみたいな判定の方がましだったかもしれません *26 。
ローカルでたくさん回して最善方法を埋め込む手も強そうな気がしました。こんなこともあるので AWS とかで分散コンピューティングとかのモチベーションが少し上がりました。
ビジュアライザ
Matrixが見やすかったので使っていました。
デバッグ窓には、実際の値、盤面ごとの(期待値・標準偏差)の組などを表示していました。このケースでは真ん中が正しいんですが、左を選んでしまいました。
緑枠部分の上から 3 行目を見ると、実際の値(29)が から来たか から来たかで判定ができるはず *27 なんですが、微妙な位置にいて判定をミスってしまったパターンです。
反省
思ったとおりの結果が出ないときに、コードベースのエラーチェックしかできてなかったので、仮説が正しい検証を逐一入れていればもう少し早めに起動修正できたかもしれません。
次回以降は分散コンピューティングを含め、作業環境をもう少し整えたうえで臨めればと思います。
End
*2:中心極限定理から、たくさんの確率変数の合計は正規分布に近付くという意味では正当性がありそうですが、自由度が小さい場合の裾野の厚さの問題と、独立性が必ずしも言えないことによる問題があります。
*3:連続分布の場合は密度関数
*4:一般的には最尤推定というと(連続)パラメータを推定する際に用いるため、本問のように 個からひとつを選ぶという趣旨とは異なることが多いですが、条件付き確率(密度)の最大化という意味で共通しているので本記事では「最尤推定」と呼んでいます。
*5:厳密な判定が現実的にできるかどうかは別として
*6:問題文では大文字で となっていましたが、後述の正規分布の記号と紛らわしいので小文字で記載しています
*7: 行 列が なら頂点 と頂点 の間に辺がある、 なら辺がない。
*8:この意味でグラフを盤面と言ったりします
*9: DP など
*10:全体の辺の本数は頂点によらないので大丈夫ですが、その他の特徴量はすべて問題になります
*11:より正確にするには順序統計量を考慮するなどが必要ですが、ちょっと大変そうです。逆転が起きない前提で、同じパラメータの頂点の組合せ数を考慮する方法もありそうです
*12: たとえば
*13:二項分布は が極端に小さくなくて がある程度大きければ正規分布に近くなります
*14:もちろん、完全に連動するわけではないので 通常は2 倍よりはだいぶ小さいはずです
*15:異なる文字は異なる頂点を表していると思ってください
*16:反クリークの判定が強い
*17:クリークが強い
*18:平均が同じものの中でクリークの期待値が最も小さくなる
*19:2 段目の階段の境目付近のクリーク判定が強い
*20:厳密な計算ではないので推定と言った方が良いかもしれません
*21:10^-6 オーダーとか
*22:10 万回やって全ケースとか
*23:これはこれで独立性が弱くなりますが、偏差が最大の特徴量を使うなどでカバーできるかもです
*24:手元実行環境はいまいちなのですが、 1 ケース流しただけでだめさ加減が分かるぐらいひどいので提出までいけなかったものもたくさんあります
*25:プレテスト時点で 58 位・・
*26:ただ実行時間的には PyPy コードテストでパラメータによっては 1-2 回しか回せなさそうだったのでもう少し工夫が必要そうでした
*27:この 2 盤面の差が最も顕著に表れる部分という意味で