宝くじ仮説の枝刈りをnumpyで自前実装したら、当たりくじの優位はスパース率98%から先だけだった(99%で62%対48%)
約15分で読めます

宝くじ仮説の枝刈りをnumpyで自前実装したら、当たりくじの優位はスパース率98%から先だけだった(99%で62%対48%)


宝くじ仮説(Lottery Ticket Hypothesis)は、枝刈り(プルーニング)の分野で一番有名な仮説だと思う。Frankle & Carbin (2019)の主張はこうだ——学習済みのニューラルネットワークから大部分の重みを削って作ったスパースな部分ネットワークは、「学習開始時の初期値」まで巻き戻してから単体で再学習すると、元の密なネットワークに匹敵する精度まで到達できる。つまりランダム初期化された密なネットワークの中には、最初から「当たりくじ」の部分ネットワークが埋まっていて、学習とはそれを見つける作業だった、という読み方ができる。「1つの密なネットワークの中に部分ネットワークが眠っている」という筋書きはDropoutを暗黙のアンサンブルとして検証した回と似ているが、あちらは部分ネットワークを平均して使い、こちらは1枚だけ選び抜いて残す。ポイントは巻き戻しで、同じスパース構造でも初期値を引き直すと精度が落ちる、というのが仮説の核心部分だ。初期化の標準偏差を振った回では初期値が学習の成否そのものを決めていたが、宝くじ仮説はさらに踏み込んで「どの重みが当たりか」まで初期値が決めていると言っている。

論文の実験はMNIST(28×28)のLeNetやCIFAR-10の畳み込みネットで行われている。では、もっとずっと小さい世界——sklearnに同梱されている8×8の手書き数字(1797枚、64ピクセル)と、隠れ層1つの小さなMLP——でもこの仮説は成り立つのだろうか。パラメータが1万個を切るような小規模ネットでは、そもそも「くじ」に当たり外れが生まれる余地がないかもしれない。逆に、極端に削ったときだけ差が出るのかもしれない。フレームワークの枝刈りAPIを使うと中で何が起きているのか分からなくなるので、順伝播・逆伝播・最適化・枝刈りまで全部numpyで書いて確かめてみた。

実験に使ったコードの全文はGitHubに置いています

実験設計: 64→128→10のMLPを、反復的マグニチュード枝刈りで99%まで削る

データはsklearn.datasets.load_digitsの8×8手書き数字1797枚を、訓練1437枚・テスト360枚に分割した。ネットワークは64→128→10の2層MLP(ReLU、He初期化、softmax交差エントロピー、Adam、バッチ64、60エポック)で、重みは全部で9472個(バイアス138個は枝刈り対象外)。この1回の学習が手元のCPUで約0.5秒で終わるので、全条件を総当たりで回せる。

枝刈りは反復的マグニチュード枝刈り(iterative magnitude pruning)で行う。学習済みの重みを絶対値の小さい順に削ってマスクを作り、生き残った重みを学習開始時の初期値θ0\theta_0に巻き戻して再学習し、それをまた削る——を繰り返して、スパース率(削った重みの割合)50%→70%→80%→90%→95%→98%→99%のマスクを順に作っていく。削る量は層ごとに同率にした(重み行列ごとに、その層の重みの絶対値下位から削る)。

def prune_layerwise(params, mask, target_sparsity):
    """今生きている重みのうち、絶対値の大きい方から
    (1 - target_sparsity) の割合だけを残す新しいマスクを作る"""
    new_mask = {k: v.copy() for k, v in mask.items()}
    for k in ("W1", "W2"):
        w = np.abs(params[k]) * mask[k]
        n_keep = int(round(w.size * (1.0 - target_sparsity)))
        order = np.argsort(w.flatten())[::-1]   # 絶対値の降順
        nm = np.zeros(w.size)
        nm[order[:n_keep]] = 1.0
        new_mask[k] = nm.reshape(params[k].shape)
    return new_mask

各スパース率で、次の3条件を比較する。

  • 当たりくじ: 枝刈りで得たマスク + 元の初期値θ0\theta_0に巻き戻して再学習
  • 同じマスク+ランダム再初期化: マスクは同じまま、初期値だけ新しく引き直す(仮説が正しければ、これは当たりくじに負けるはず)
  • ランダムなマスク+元の初期値: マスクの構造自体をランダムにする(層ごとの生存数は揃える)

これをシード5個(初期値とミニバッチ順を変える)で回した。学習の総回数は110回、全部で43秒だった。ちなみにスパース率99%まで削ると、生き残る重みは9472個中たった95個(第1層82個、第2層13個)になる。

結果1: スパース率95%までは、当たりくじと再初期化の差は1〜2ポイントしかない

まず、スパース率ごとの3条件のテスト精度を折れ線で見る。

スパース率50%から99%までの各条件のテスト精度を示す折れ線グラフ。横軸はスパース率、縦軸はテスト精度で、上部に灰色の破線で枝刈りなしの密なネットワークの精度98.1%が引かれている。青い丸のラインが当たりくじ(マスク+元の初期値)、オレンジの四角が同じマスク+ランダム再初期化、緑の三角がランダムなマスク+元の初期値で、各ラインの周囲には5シードの標準偏差が半透明の帯で示されている。3本とも80%までは95%以上の高い位置でほぼ重なっているが、緑のランダムマスクだけが90%から落ち始めて95%で63%、98%で24%、99%で16%まで急落する。青とオレンジは95%まで90%台でほぼ並走し、98%から差が開いて99%では青が62%、オレンジが48%で終わる

数字で見るとこうなる(5シード平均)。

スパース率     当たりくじ   同マスク+再初期化   ランダムマスク
  50%         98.2%        97.4%             97.4%
  70%         97.8%        96.8%             95.9%
  80%         97.3%        95.5%             94.8%
  90%         95.1%        94.4%             89.0%
  95%         93.1%        91.4%             63.2%
  98%         75.7%        64.4%             23.9%
  99%         61.6%        47.9%             15.6%
(枝刈りなしの密なネットワーク: 98.1%)

まず驚くのは枝刈り自体の頑健さで、重みの95%を削っても(9472個→474個)、当たりくじは93.1%、初期値を引き直しても91.4%出る。この時点で当たりくじと再初期化の差はわずか1.7ポイントだ。スパース率50〜95%の範囲では、差は一貫して0.7〜1.8ポイントしかない。「同じマスクなら初期値を引き直してもほぼ同じ精度が出る」わけで、この範囲だけ見ると宝くじ仮説の核心部分(初期値が大事)は、ほとんど確認できない。

一方で、マスクの構造の効果はもっと早くから現れる。ランダムマスクは90%で89.0%に落ち、95%では63.2%まで崩壊する。同じ474個の重みでも、枝刈りで選んだ配置なら91〜93%、ランダムな配置なら63%。どの重みを残すか(構造)は、95%の時点ですでに28ポイント分の価値がある

結果2: 初期値の優位は、98%を超えると一気に11〜14ポイントに開く

スパース率×戦略のヒートマップで全体を見る。

スパース率と戦略のテスト精度ヒートマップ。行は上から当たりくじ(マスク+元の初期値)、同じマスク+ランダム再初期化、ランダムなマスク+元の初期値の3戦略、列はスパース率50%・70%・80%・90%・95%・98%・99%の7段階で、各セルに5シード平均の精度がパーセントで書き込まれ、精度が高いほど濃い青、低いほど白に近い色になっている。左側の低スパース率の列は3行とも濃い青(94〜98%)だが、右に行くにつれ下の行から順に色が抜けていく。ランダムマスクの行は95%で63.2、99%で15.6と白くなり、再初期化の行は98%で64.4、99%で47.9、当たりくじの行は98%で75.7、99%で61.6と、右下の角に向かって明確な段差ができている

当たりくじと再初期化の差(=初期値の巻き戻しの価値)をスパース率ごとに並べると、構図がはっきりする。

スパース率:   50%   70%   80%   90%   95%   98%    99%
当たりくじの優位: +0.8  +1.0  +1.8  +0.7  +1.7  +11.2  +13.7 (ポイント)

95%までは1〜2ポイントで横ばいだった差が、98%(生き残り190個)で+11.2ポイント、99%(生き残り95個)で+13.7ポイントへと一気に開く。98〜99%の当たりくじはシード間のばらつきも大きい(99%で61.6±6.1%)が、差の11〜14ポイントはそのばらつきを超えている。5シードすべてで当たりくじが再初期化を上回った。

つまりこの小さな世界では、宝くじ仮説は「成り立たない」のではなく、極端なスパース率でだけ観測可能になる。重みが数百個も残っていれば、良い構造さえあればどんな初期値からでも学習し直せてしまう。初期値の善し悪しが生死を分けるのは、重みが100個前後しか残らない崖っぷちの領域だった。

結果3: 最終精度が並ぶ95%でも、当たりくじは「速さ」で勝っていた

スパース率95%は最終精度の差が1.7ポイントしかない領域だが、学習曲線を見ると別の差が隠れていた。

スパース率95%における当たりくじ(青)と同じマスク+ランダム再初期化(オレンジ)のテスト精度の学習曲線。横軸はエポック(1〜60)、縦軸はテスト精度で、5シード平均の線の周りに標準偏差の帯が付いている。青の当たりくじはエポック1ですでに72%から始まり、5エポックで84%、10エポックで88%に達してそのまま緩やかに93%へ収束する。オレンジの再初期化はエポック1で18%からスタートし、序盤は帯も大きく広がりながら急な坂を登り、20エポックで82%、最終的に91%に到達して青との差を詰めるが、全区間を通じて一度も青を上回らない

当たりくじは1エポック目の時点でテスト精度72.1%に達している。再初期化は同じ時点で18.4%。5エポック時点でも84.3%対45.7%で、再初期化が80%台に乗るのは20エポック近くかかる。60エポックかければ91.4%まで追いつくが、序盤の挙動は全く別物だ。元論文でも当たりくじは「同等以上の精度に、より速く到達する」と主張されているが、それがこの8×8のおもちゃのような設定でも再現された。最終精度だけ見ると「初期値はほぼ関係ない」ように見える95%でも、初期値の優位は最終精度に現れる前に、まず学習の速さに現れている

枝刈りが残す「構造」をGIFで見る

第1層の重み行列(64ピクセル×128ユニット)のマスクが、枝刈りが進むにつれてどう疎になっていくかをアニメーションにした。右のパネルは、入力側の各ピクセル(8×8に並べ直したもの)から何本の結線が生き残っているかを示す。

枝刈りの進行を示すアニメーション。左のパネルは第1層の重み行列(縦64入力ピクセル×横128隠れユニット)のマスクで、生き残っている重みが黒い点で描かれる。最初は全面真っ黒(密)だが、スパース率50%、70%、80%と進むにつれて黒い点がまばらになり、99%では82個の点がぽつぽつと散る程度になる。右のパネルは入力の8×8ピクセルごとの生き残った結線数の濃淡マップで、枝刈りが進むと画像の左端の列(手書き数字データでほぼ常にゼロの領域)から色が抜けて白くなり、数字が実際に描かれる中央〜右寄りの領域に濃い青が残っていく

スパース率99%の時点で、64個の入力ピクセルのうち22個は結線が1本も残っていない。つまり枝刈りは事実上の特徴選択を行っていて、「このピクセルはそもそも見ない」という判断を自動でやっている。実際、digitsデータで値が全サンプル完全にゼロのピクセルが3個ある(左上角など)が、この3個はきれいに全滅していた。ただし過大評価もしないでおくと、生き残ったピクセルの分散の平均は21.2、全滅したピクセルは14.2で傾向はあるものの、ピクセルの分散と生存結線数の相関係数は0.115と弱い。「情報のあるピクセルを選んでいる」とまでは言えず、「情報が完全にないピクセルは確実に捨てる」くらいが実測に忠実な表現だ。

正直に書いておくべきこと

  • 8×8・重み1万個未満の世界で出た結果を、大規模ネットワークに一般化することはできない。 これが一番大事な注意で、元論文の主戦場(LeNet、VGG、ResNet)とはパラメータ数が3〜7桁違う。この記事が言えるのは「この小さな設定でも仮説の核心(初期値の優位)が観測でき、ただしそれは極端なスパース率に限られた」ということだけだ。むしろ後続研究(Frankle et al. 2020など)では、大規模ネットでは初期値そのものへの巻き戻しは効かず、学習序盤の重みへの巻き戻しが必要になることが知られていて、「どのスケールで・どの条件なら巻き戻しが効くか」自体が研究テーマになっている。
  • 枝刈りは層ごとの同率マグニチュード枝刈りで、全体一括(グローバル)の枝刈りや構造化枝刈りは試していない。スパース率99%では第2層(128×10)の生き残りが13個しかなく、この層の壊れ方が全条件の精度低下を主導している可能性がある。
  • 学習は60エポック固定。結果3で見たとおり再初期化は立ち上がりが遅いので、もっと長く学習すれば98〜99%の差の一部は縮むかもしれない(95%では実際に91.4%まで追いついた)。
  • シードは5個、テストセットは360枚なので、1枚の正誤で精度が0.28%動く。50〜95%の1〜2ポイント差は、この解像度では「ほぼ差がない」と読むのが安全だと思う。

手を動かして意外だったこと

一番意外だったのは、3条件が別々のタイミングで脱落していくことだ。実験前は「当たりくじ vs その他」という2グループの絵を予想していたが、実際には、まずスパース率90〜95%でランダムマスクが脱落し(構造が効き始める)、98%で再初期化が脱落する(初期値が効き始める)。「どの重みを残すか」と「その重みがどんな値から出発するか」は、同じ「当たりくじ」の構成要素なのに、効き始めるスパース率が全然違う。仮説の検証としては「95%まで差が出ない」という一見ネガティブな結果と「98%から14ポイント差が出る」というポジティブな結果が同居していて、どちらか片方のスパース率だけ試していたら正反対の結論を書いていたはずだ。

もう1つは、最終精度に差が出ない領域でも学習曲線には最初から差が付いていたこと。1エポック目で72%対18%という開きは、乱数のゆらぎではなく初期値とマスクの噛み合わせがそもそも違うことを示している。「差がない」ように見える設定でも、どの軸で測るかによって差は既に存在している——これは実験の設計を考えるうえで覚えておきたい教訓だった。

まとめ

  • 8×8手書き数字(sklearn digits)+numpy自前実装の2層MLP(重み9472個)で、反復的マグニチュード枝刈りによりスパース率50〜99%のマスクを作り、「当たりくじ(マスク+元の初期値)」「同じマスク+ランダム再初期化」「ランダムなマスク」を5シードで比較した
  • 枝刈りなしの精度98.1%に対し、スパース率95%(生き残り474個)でも当たりくじは93.1%を維持。当たりくじと再初期化の差は95%まで0.7〜1.8ポイントしかなく、この範囲では初期値の優位はほぼ観測できなかった
  • マスクの構造の効果は先に現れ、ランダムマスクは95%で63.2%に崩壊(枝刈りマスクとの差は28ポイント)。枝刈りは分散ゼロのピクセルへの結線を確実に削る「特徴選択」として働いていたが、生存結線数とピクセル分散の相関は0.115と弱かった
  • 初期値の優位はスパース率98%(+11.2ポイント)、99%(61.6%対47.9%、+13.7ポイント)で一気に現れた。小規模ネットでも宝くじ仮説の核心は成り立つが、それは重みが100個前後しか残らない極端な領域に限られた
  • 最終精度がほぼ並ぶスパース率95%でも、学習曲線では1エポック目から72.1%対18.4%と大差が付いており、初期値の優位は最終精度より先に学習速度に現れていた