モダン活性化関数の完全ガイド — SiLU・GELU・Mishを数式から理解する

GPTやBERTのようなTransformerの中身を覗くと、ReLUではなくGELUという見慣れない活性化関数が使われています。画像認識のEfficientNetやYOLO系ではSiLU(Swish)が、物体検出の一部ではMishが標準になりました。なぜ、長らく王座にあったReLUから、これらの「滑らかな曲線」へと主役が移ったのでしょうか。

活性化関数は、ニューラルネットワークに非線形性を与えるたった一つの小さな関数です。しかしこの選択が、学習が安定するか、勾配が深い層まで届くか、最終的な精度がどこまで伸びるかを大きく左右します。本記事では、まず活性化関数がなぜ必要かを押さえたうえで、ReLUの利点と限界を確認し、そこからSiLU・GELU・Mishという3つのモダン活性化関数を定義・微分・なぜ効くかまで丁寧に分解していきます。比較対象としてLeaky ReLU・ELU・Softplusにも触れ、最後はnumberだけでスクラッチ実装します。

本記事の内容

  • 活性化関数の役割と、非線形性がなぜ必須なのか
  • ReLUの強さと「dying ReLU」という弱点
  • SiLU/Swish・GELU・Mishの定義と微分、そして「なぜ効くのか」
  • 勾配の流れ・滑らかさ・自己ゲーティングという3つの観点
  • 実務での選び方と代表的な採用例(Transformer系のGELUなど)
  • numpyによるfrom-scratch実装

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

活性化関数の役割 — なぜ非線形性が要るのか

ニューラルネットワークの各層がやっていることは、突き詰めると「入力に重みを掛けて足し、バイアスを足す」という線形変換です。イメージとしては、定規で直線を引くようなものです。直線をどれだけ重ねても、出てくるのは結局1本の直線にしかなりません。これは数式でもすぐに確かめられます。2つの線形変換 $\bm{W}_2(\bm{W}_1\bm{x} + \bm{b}_1) + \bm{b}_2$ を展開すると $(\bm{W}_2\bm{W}_1)\bm{x} + (\bm{W}_2\bm{b}_1 + \bm{b}_2)$ となり、これは別の重み $\bm{W}’ = \bm{W}_2\bm{W}_1$ を持つ、たった1層の線形変換と同じものです。

つまり、活性化関数がなければ、何百層積み重ねても表現力は1層分しかありません。曲がった境界を引くことができず、有名なXOR問題すら解けないのです。各層の出力に非線形な関数を挟むことで、初めて「曲げる」操作が可能になり、ネットワークは複雑な関数を近似できるようになります。この非線形性こそが深層学習の表現力の源泉です。非線形分離がどのように効くかについては【pytorch】深層学習の非線形分離性能を確認するで実際の挙動を確認できます。

活性化関数に求められる性質は、ざっくり次の3つにまとめられます。

  • 非線形であること — そもそもの存在意義。線形だと層を重ねる意味がない。
  • 微分可能(あるいはほぼ可能)であること — 誤差逆伝播法は勾配を必要とする。微分が扱いやすいほど学習しやすい。
  • 勾配が消えにくいこと — 入力が大きくても小さくても、微分がゼロに張り付かないほうが、深い層まで勾配が届く。

この3つの観点、特に最後の「勾配が消えにくいか」が、ReLUから先のモダン活性化関数を理解する鍵になります。では、まずReLUがなぜこれほど普及したのかを見ていきましょう。

ReLUの利点と限界 — dying ReLU問題

ReLU(Rectified Linear Unit)の定義は拍子抜けするほど単純です。負ならゼロ、正ならそのまま通すだけです。

$$ \mathrm{ReLU}(x) = \max(0,\ x) $$

この単純さがReLUの最大の武器でした。シグモイドやtanhが主流だった時代、深いネットワークは「勾配消失」に苦しんでいました。シグモイドの微分は最大でも $0.25$ にしかならず、層を遡るたびに勾配が $0.25$ 倍、$0.25^2$ 倍と指数的に縮んでいくため、入力側の層がほとんど学習できなかったのです。

ReLUはこの問題を一気に解決しました。正の領域では微分がちょうど $1$ になります。

$$ \frac{d}{dx}\mathrm{ReLU}(x) = \begin{cases} 1 & (x > 0) \\ 0 & (x < 0) \end{cases} $$

微分が $1$ ということは、勾配を縮めも増やしもせず、そのまま後ろの層へ流すということです。何層遡っても正の経路では勾配の大きさが保たれます。さらに計算は比較演算1回だけで、指数関数を含むシグモイドよりはるかに高速です。この「勾配を保つ」「速い」という2点で、ReLUは2010年代の深層学習を支える標準になりました。

しかし、ReLUには見過ごせない弱点があります。負の領域では出力も微分も完全にゼロです。学習の途中で、あるニューロンの入力(前活性 $z$)が常に負になるような重みに落ち込んでしまうと、そのニューロンは出力ゼロを返し続け、微分もゼロなので勾配が一切流れなくなり、もう二度と重みが更新されない状態に陥ります。これがdying ReLU(死んだReLU)問題です。大きな学習率や不運な初期化で、ネットワークの何割ものニューロンが「死ぬ」ことすらあります。

dying ReLU問題とSiLUの微分の比較図解

左の図で赤く塗った負の領域は、ReLUが出力ゼロ・微分ゼロになる「死の領域」です。右の図を見ると、ReLUの微分は原点で $0$ から $1$ へ階段状に不連続です。一方でSiLUの微分(オレンジ)は負側でも完全にはゼロにならず、滑らかにつながっています。この「負側でも勾配が少し流れる」性質が、後で見るモダン活性化関数の共通の狙いです。

dying ReLUへの最初の処方箋は、負側にわずかな傾きを与えることでした。次に、その素朴な改良版から見ていきましょう。

ReLUの素朴な改良 — Leaky ReLU・ELU・Softplus

dying ReLUの原因は「負側の微分がゼロ」でした。ならば負側にも小さな傾きを残せばよい、という発想がLeaky ReLUです。

$$ \mathrm{LeakyReLU}(x) = \begin{cases} x & (x \ge 0) \\ \alpha x & (x < 0) \end{cases} \qquad (\alpha \approx 0.01) $$

負側でも微分が $\alpha$(ゼロでない)なので、ニューロンが完全に死ぬことはありません。ただし関数値も微分も原点でカクッと折れ曲がっており、滑らかさは持ちません。

ELU(Exponential Linear Unit)は、負側を指数関数で滑らかにつなぎ、出力の平均をゼロに近づけることを狙った関数です。

$$ \mathrm{ELU}(x) = \begin{cases} x & (x \ge 0) \\ \alpha(e^{x} – 1) & (x < 0) \end{cases} $$

負側が滑らかな曲線になり、$x \to -\infty$ で $-\alpha$ に飽和します。出力の平均がゼロ寄りになることで、後続の層の学習が安定しやすいという利点があります。

Softplusは、ReLUそのものを滑らかに近似した関数です。

$$ \mathrm{Softplus}(x) = \log(1 + e^{x}) $$

この微分はちょうどシグモイド関数 $\sigma(x) = 1/(1 + e^{-x})$ になります。どこでも微分可能で「角がない」ReLUと言えますが、常に正の値を返し、原点付近でReLUより少し膨らむため、そのままではReLUを置き換えるほどの性能は出ませんでした。それでも、後でMishの中に再登場する重要な部品です。

これらの素朴な改良は「負側で勾配を残す」「滑らかにする」という方向性を示しました。しかし真の主役は、まったく別の発想から生まれます。それが「入力自身が自分の通り具合を決める」自己ゲーティングです。

SiLU / Swish — 自己ゲーティングの発見

Leaky ReLUやELUは「負側をどう処理するか」を人手で設計しました。これに対してSiLU(Sigmoid Linear Unit、別名Swish)は、もっと素朴で美しいアイデアに基づいています。入力 $x$ に、その入力自身から作ったゲート $\sigma(x)$ を掛けるのです。

自己ゲーティングの直感を表す模式図。入力xがゲートσ(x)と値xに分かれ掛け合わされる

上の図がSiLUの仕組みです。入力 $x$ が2つの経路に分かれます。一方はそのまま「値」として、もう一方はシグモイドを通って $0$〜$1$ の「ゲート開度」になります。最後に両者を掛け合わせると出力になります。$x$ が大きく正ならゲートはほぼ全開($\sigma(x)\approx 1$)でほぼ素通り、$x$ が大きく負ならゲートはほぼ閉じて($\sigma(x)\approx 0$)出力はほぼゼロ。つまり入力自身が「自分をどれだけ通すか」を決める——これが自己ゲーティング(self-gating)です。

SiLUの定義と性質

数式にすると驚くほどシンプルです。

$$ \mathrm{SiLU}(x) = x\,\sigma(x) = \frac{x}{1 + e^{-x}} $$

この関数には、ReLUにない3つの特徴があります。第1に、どこでも滑らか(無限回微分可能)です。原点でカクッと折れたりしません。第2に、負側では完全にゼロにならず、$x \approx -1.28$ あたりで最小値(約 $-0.28$)をとるわずかな谷を持ちます。この谷のおかげで、負の前活性を持つニューロンにも少しだけ勾配が流れ、dying ReLU問題が緩和されます。第3に、$x$ が大きい領域ではほぼ $x$ そのもの(ReLUと同じ振る舞い)に漸近するため、ReLUの「勾配を保つ」長所も受け継いでいます。

SiLUの微分

SiLUの微分は、積の微分公式と「シグモイドの微分が $\sigma'(x) = \sigma(x)(1-\sigma(x))$ である」という事実から導けます。まず積の微分を適用します。

$$ \frac{d}{dx}\big(x\,\sigma(x)\big) = \sigma(x) + x\,\sigma'(x) $$

ここで $\sigma'(x) = \sigma(x)(1-\sigma(x))$ を代入すると、次のようにシグモイドだけで書けます。

$$ \mathrm{SiLU}'(x) = \sigma(x) + x\,\sigma(x)\big(1 – \sigma(x)\big) $$

この式を $\sigma(x)$ でくくると、SiLU自身を使った見通しの良い形にも整理できます。

$$ \mathrm{SiLU}'(x) = \sigma(x)\big(1 + x(1 – \sigma(x))\big) = \mathrm{SiLU}(x) + \sigma(x)\big(1 – \mathrm{SiLU}(x)\big) $$

注目すべきは、この微分が最大で約 $1.1$ を超える点です。ReLUの微分が頭打ち $1$ なのに対し、SiLUは正側で一時的に $1$ より大きな勾配を持ちます。これは「ちょうど活性化が立ち上がる領域で、信号を少し増幅して後ろへ流す」ことを意味し、学習を加速する一因と考えられています。

SiLUはニューラルアーキテクチャ探索(NAS)の研究で、自動探索の結果として「ReLUを置き換えるとよい関数」として再発見されました。理論的にひねり出したというより、「実際に試したら強かった」関数だという点も興味深いところです。次に、確率論からの裏付けを持つGELUを見ていきましょう。

GELU — ガウス分布によるゲーティング

SiLUは「シグモイドでゲートする」という発想でした。GELU(Gaussian Error Linear Unit)は、ここに確率的な意味づけを与えます。アイデアは「入力 $x$ を、その値が標準正規分布のもとで起こりやすいかどうかの確率で通す」というものです。

具体的には、ニューロンへの入力にノイズが乗っていると考え、「入力 $x$ をそのまま残すか、ゼロにするか」を、$x$ が標準正規分布から引いた別の値より大きいかどうかで確率的に決めます。その期待値をとると、ゲートが標準正規分布の累積分布関数(ガウスCDF)$\Phi(x)$ になります。

GELUの定義

$$ \mathrm{GELU}(x) = x\,\Phi(x), \qquad \Phi(x) = \frac{1}{2}\left[1 + \mathrm{erf}\!\left(\frac{x}{\sqrt{2}}\right)\right] $$

ここで $\Phi(x)$ は標準正規分布の累積分布関数、$\mathrm{erf}$ は誤差関数です。SiLUがシグモイド $\sigma(x)$ でゲートしたのに対し、GELUはガウスCDF $\Phi(x)$ でゲートしている——構造はそっくりで、ゲート関数が違うだけです。$\Phi(x)$ は $x$ が小さいときほど「通す確率」が低く、大きいときほど高くなる、$0$ から $1$ へ滑らかに立ち上がるS字曲線です。

ガウスCDF近似

$\Phi(x)$ には初等関数による閉じた形がないため、実装では2種類の近似がよく使われます。1つはtanhを使う近似です。

$$ \mathrm{GELU}(x) \approx \frac{1}{2}x\left[1 + \tanh\!\left(\sqrt{\frac{2}{\pi}}\big(x + 0.044715\,x^{3}\big)\right)\right] $$

もう1つは、もっと大胆にシグモイドで近似する形で、これは $\Phi(x) \approx \sigma(1.702\,x)$ とみなすものです。

$$ \mathrm{GELU}(x) \approx x\,\sigma(1.702\,x) $$

この近似式を見ると、GELUとSiLUの近さが一目瞭然です。SiLUは $x\,\sigma(x)$、GELUは $x\,\sigma(1.702 x)$。つまりGELUは「ゲートを少し急にしたSiLU」とも解釈できます。

GELUの厳密版とtanh近似、およびガウスCDFゲートの比較

左の図のとおり、GELUの厳密版(青)とtanh近似(赤破線)はほぼ完全に重なっており、実用上は近似で十分です。右の図は2つのゲート関数の比較で、ガウスCDF $\Phi(x)$(緑)とシグモイド近似 $\sigma(1.702x)$(紫破線)がよく一致しています。どちらも原点付近にわずかな負の谷を持ち、$x\to-\infty$ で滑らかにゼロへ近づく点がReLUとの決定的な違いです。

GELUの微分

GELUの微分も積の微分から導けます。$\Phi(x)$ を微分すると標準正規分布の確率密度関数 $\phi(x) = \frac{1}{\sqrt{2\pi}}e^{-x^2/2}$ になることを使います。

$$ \mathrm{GELU}'(x) = \frac{d}{dx}\big(x\,\Phi(x)\big) = \Phi(x) + x\,\phi(x) $$

第1項 $\Phi(x)$ は $0$〜$1$ のゲート開度そのもの、第2項 $x\,\phi(x)$ は原点付近で生じる補正項です。この微分も滑らかで、負側で完全にはゼロにならないため、勾配が流れ続けます。

GELUは現在のTransformer系モデルの事実上の標準活性化関数です。BERT・GPT・ViT(Vision Transformer)など、名だたるモデルがフィードフォワード層にGELUを採用しています。Transformerの内部構造についてはTransformerをゼロから実装して理解するも参考になります。続いて、もう一段滑らかさを推し進めたMishを見ましょう。

Mish — Softplusを通したtanhゲーティング

Mishは、SiLUの自己ゲーティングの考え方に「もっと滑らかで、もっと豊かな負側」を求めて設計された関数です。ゲートにシグモイドではなく、Softplusを通したtanhを使います。

$$ \mathrm{Mish}(x) = x\,\tanh\!\big(\mathrm{softplus}(x)\big) = x\,\tanh\!\big(\log(1 + e^{x})\big) $$

一見複雑ですが、構造はSiLUと同じ「$x \times$ ゲート」です。ゲート部分 $\tanh(\mathrm{softplus}(x))$ は $0$〜$1$ に近い値をとる滑らかなS字で、SiLUのシグモイドゲートよりも負側でゆるやかに立ち下がります。

Mishの関数値と微分の形状

左の図でMish(茶)とSiLU(橙破線)を比べると、関数値はよく似ていますが、Mishのほうが負側の谷がわずかに深く、立ち下がりがなだらかです。右の微分の図では、Mishの微分がSiLUよりさらに滑らかに変化し、負側に広がる非単調な「ふくらみ」を持つことがわかります。この豊かな勾配の形状が、情報を細かく保持しながら伝える助けになると言われています。

Mishの利点は「上に有界でなく(正側で頭打ちしない)、下に有界(負側で飽和する)、かつ全域で滑らか」という3点が同時に成り立つことです。物体検出のYOLOv4などで採用され、ReLUやSiLUより精度が向上した報告があります。一方で、$\tanh$ と $\log$ と $\exp$ を含むため計算コストはReLUよりかなり高く、この重さが普及の足かせにもなっています。

ここまで4つのモダン活性化関数を見てきました。次は、それらを同じ土俵に並べて、形状と微分を一望してみましょう。

各関数と微分の形状比較

言葉で性質を並べるより、重ねて描いたほうが違いがはっきりします。まず関数値そのものです。

ReLU・SiLU・GELU・Mishの関数値を重ねた比較グラフ

この図から読み取れることは3つあります。第1に、正側ではどの関数も $x$(45度線)に漸近しており、大きな正の入力に対しては「ほぼ素通し」という点でReLUと共通します。第2に、原点付近の滑らかさが違います。ReLUだけが折れ曲がり、他の3つは曲線で滑らかに立ち上がります。第3に、負側でSiLU・GELU・Mishはわずかな谷を持ち、ReLUのようにスパッとゼロにはなりません。SiLUとGELUはほとんど重なって見え、Mishはわずかに谷が深いという序列です。

次に、学習にとって本当に重要な微分を見ます。

各活性化関数の微分(導関数)の形状比較グラフ

微分の図はさらに雄弁です。ReLUの微分(青)は原点で $0$ から $1$ へ垂直に飛ぶ階段で、不連続です。一方、SiLU・GELU・Mishの微分はすべて滑らかな曲線で、しかも正側で一時的に $1$ を超える(最大約 $1.1$ 前後)「オーバーシュート」を持ちます。この $1$ 超えが、活性化の立ち上がり領域で勾配を少し増幅し、学習を後押しします。負側でも微分がゆるやかにゼロへ近づくため、dying問題が起きにくいことも見て取れます。

ReLUと滑らかな自己ゲーティング系の違いを、原点付近に絞ってさらに拡大してみましょう。

ReLUとSiLUの原点付近の拡大比較。関数値と微分

左は関数値、右は微分です。関数値(左)では、ReLUが原点でカクッと折れるのに対しSiLUは滑らかにつながります。微分(右)では、ReLUが原点で不連続にジャンプするのに対し、SiLUの微分は連続です。最適化の観点では、微分が連続であるほど勾配が暴れにくく、損失の地形が滑らかになって学習が安定します。これがモダン活性化関数の効きどころの一つです。

次は、これらの形状の違いが「負の入力」でどう表れるかをまとめて確認します。

負側の挙動と勾配の流れ

これまで何度も「負側で完全にゼロにならない」という性質を強調してきました。その違いを負側に絞って並べてみます。

負の入力に対する各活性化関数の挙動比較

ReLUは負側で水平ゼロのままです。Leaky ReLUは負側に一定の傾きの直線、ELUは滑らかに $-1$ へ飽和します。SiLUとMishは負側に「谷」を作り、いったん少しマイナスに落ちてから再びゼロへ戻ります。この谷が表しているのは「ほどほどに負の入力なら、少しだけ負の値を通す」という柔らかいゲーティングです。完全に締め出すReLUと違い、わずかな情報と勾配を残すことで、ニューロンが死なずに済みます。

では、この「負側で勾配が残る」「滑らか」という性質は、深いネットワークの学習にどう効くのでしょうか。逆伝播では、勾配が層を遡るたびに各層の活性化関数の微分が掛け合わされます。微分が小さすぎれば積はゼロへ吸い込まれ(勾配消失)、入力側の層が学習できなくなります。

深いネットでの勾配の連鎖積の減衰比較(対数軸)

この図は、ランダムな前活性を通したときに各活性化関数の微分の積(連鎖積)が層を遡るにつれてどう減るかを、対数軸でシミュレートしたものです。シグモイドは微分の上限が $0.25$ なので最も速く消失します。ReLUは正側を通れば微分 $1$ で勾配を保ちますが、いったん負の経路に入ると微分ゼロで連鎖積が一気に床(ゼロ)へ落ちます。SiLUはその中間で、微分がゼロに張り付かないぶんReLUより緩やかに減衰します。あくまで簡易シミュレーションですが、「滑らかで負側もゼロでない活性化は勾配を保ちやすい」という傾向の直感を与えてくれます。

ここまでで、3つの観点——勾配の流れ(深い層まで勾配が届くか)、滑らかさ(損失の地形がなめらかで最適化が安定するか)、自己ゲーティング(入力自身がゲートを決める柔軟さ)——が出そろいました。これらを踏まえて、実務でどう選ぶかを整理します。

実務での選び方と代表的な採用例

「結局どれを使えばいいのか」という問いには、タスクとモデルによる、というのが正直な答えです。とはいえ、現場で通用する目安はあります。

  • まず迷ったらReLU — 計算が最速で、十分に強い。CNNの中間層や、とにかく速く回したいベースラインでは今でも第一候補です。dying ReLUが疑われたらLeaky ReLUに切り替えます。
  • Transformer系ならGELU — BERT・GPT・ViTなど、Transformerのフィードフォワード層はGELUが事実上の標準です。新しくTransformerを組むなら、まずGELUを選んでおけば外しません。
  • CNNで精度を伸ばしたいならSiLU/Swish — EfficientNetやYOLO系の一部はSiLUを採用しています。ReLUからの差し替えで、計算コストの増加と引き換えに精度が伸びることがあります。
  • 滑らかさを極めたいならMish — 物体検出など一部のタスクで効果が報告されています。ただし計算コストが高いため、推論速度が重要な場面では慎重に。

選ぶ際の判断軸を整理すると、横軸に「計算コスト」、縦軸に「学習の安定性・精度の伸びしろ」を置くイメージです。ReLUはコスト最小・性能標準、GELU/SiLUはコスト中・性能高め、Mishはコスト高・性能ピーキー、という位置取りになります。大規模モデルでは活性化関数の計算が全体に占める割合は小さいため、性能優先でGELUやSiLUを選ぶのが近年の潮流です。

理論と目安を押さえたところで、これらの関数を自分の手で実装し、グラフが本記事の図と一致することを確かめましょう。

numpyでのfrom-scratch実装

まず、各活性化関数とその微分をnumpyだけで定義します。外部ライブラリには依存しません。誤差関数 erf は標準ライブラリの math から借ります。

import numpy as np
from math import erf

# シグモイドとその微分
def sigmoid(x):
    return 1.0 / (1.0 + np.exp(-x))

# ReLU
def relu(x):
    return np.maximum(0.0, x)

def d_relu(x):
    return np.where(x > 0, 1.0, 0.0)

# Softplus(数値安定版: logaddexp(0, x) = log(1 + e^x))
def softplus(x):
    return np.logaddexp(0.0, x)

# SiLU / Swish: x * sigmoid(x)
def silu(x):
    return x * sigmoid(x)

def d_silu(x):
    s = sigmoid(x)
    return s + x * s * (1.0 - s)

ここまでで自己ゲーティング系の中心であるSiLUまで定義しました。SiLUの微分が、本文で導いた $\sigma(x) + x\sigma(x)(1-\sigma(x))$ をそのままコードにしたものになっている点を確認してください。続いてGELUとMishを定義します。

# ガウスCDF Phi(x) をベクトル化(erfは標準ライブラリ)
def gauss_cdf(x):
    vf = np.vectorize(lambda t: 0.5 * (1.0 + erf(t / np.sqrt(2.0))))
    return vf(x)

# GELU(厳密版)とその微分
def gelu(x):
    return x * gauss_cdf(x)

def d_gelu(x):
    phi = np.exp(-0.5 * x ** 2) / np.sqrt(2.0 * np.pi)  # 標準正規の確率密度
    return gauss_cdf(x) + x * phi

# GELU(tanh近似版)
def gelu_tanh(x):
    c = np.sqrt(2.0 / np.pi)
    return 0.5 * x * (1.0 + np.tanh(c * (x + 0.044715 * x ** 3)))

# Mish: x * tanh(softplus(x))
def mish(x):
    return x * np.tanh(softplus(x))

GELUの微分は本文の $\Phi(x) + x\phi(x)$ をそのまま書いたものです。次に、定義した関数を可視化し、本記事の図と一致するか確かめます。

import matplotlib.pyplot as plt

x = np.linspace(-6, 6, 1201)

plt.figure(figsize=(8, 5))
plt.plot(x, relu(x), label="ReLU")
plt.plot(x, silu(x), label="SiLU / Swish")
plt.plot(x, gelu(x), label="GELU")
plt.plot(x, mish(x), label="Mish")
plt.axhline(0, color="gray", lw=0.7)
plt.axvline(0, color="gray", lw=0.7)
plt.xlabel("入力 x")
plt.ylabel("出力 f(x)")
plt.title("モダン活性化関数の比較")
plt.legend()
plt.grid(alpha=0.3)
plt.ylim(-1.5, 6)
plt.show()

このグラフは本記事の「主要なモダン活性化関数の比較」と同じ形になります。正側ではどれも $x$ に漸近し、負側ではSiLU・GELU・Mishが小さな谷を作る、という特徴を自分の手元で再現できれば実装は正しいと判断できます。最後に、GELUのtanh近似が厳密版とどれだけ一致するかを数値で確認します。

# 厳密GELUとtanh近似の最大誤差を確認
diff = np.abs(gelu(x) - gelu_tanh(x))
print(f"GELU厳密版とtanh近似の最大絶対誤差: {diff.max():.6f}")

# SiLUの微分の最大値(1を超えるか)を確認
print(f"SiLU微分の最大値: {d_silu(x).max():.4f}")
print(f"GELU微分の最大値: {d_gelu(x).max():.4f}")

このコードを実行すると、GELUのtanh近似の最大絶対誤差はおよそ $0.0005$ と非常に小さく、実用上は近似で十分だとわかります。またSiLUの微分の最大値は約 $1.10$、GELUの微分の最大値は約 $1.13$ で、いずれも本文で述べた「微分が一時的に $1$ を超える」性質が数値的に確認できます。理論で予測したことが、実装の出力ときれいに一致しました。

この $1$ 超えの意味をもう一度かみしめておきましょう。ReLUは正側の微分が常にぴったり $1$ で、勾配を縮めも増やしもせず後ろへ流すだけでした。これに対しSiLUやGELUは、活性化がちょうど立ち上がる原点付近で勾配を一時的に増幅します。深い層を遡る逆伝播のなかで、この小さな増幅が「勾配が消えがちな経路に少しだけ余力を与える」働きをし、結果として学習を後押しすると考えられています。逆に大きく正・大きく負の領域では微分が穏やかに $1$ や $0$ へ戻るため、勾配が暴走することもありません。滑らかな自己ゲーティングが「ほどよく勾配を整える」ことの一端が、たった数行の数値実験からも見て取れるわけです。

まとめ

本記事では、モダン活性化関数をSiLU・GELU・Mishを中心に解説しました。

  • 活性化関数は非線形性の源 — これがなければ何層重ねても1層分の表現力しかなく、複雑な境界を引けません。
  • ReLUの強さと限界 — 正側で微分 $1$ だから勾配を保ち高速。しかし負側は出力も微分もゼロで、dying ReLU問題を抱えます。
  • SiLU/Swish — $x\,\sigma(x)$ という自己ゲーティング。滑らかで、負側に谷を持ち、微分が一時的に $1$ を超えます。
  • GELU — $x\,\Phi(x)$ とガウスCDFでゲート。$x\,\sigma(1.702x)$ と近似でき、SiLUの親戚。Transformerの標準です。
  • Mish — $x\,\tanh(\mathrm{softplus}(x))$。最も滑らかで負側が豊かですが、計算コストは高めです。
  • 選び方 — 迷ったらReLU、TransformerならGELU、CNNで精度を伸ばすならSiLU、という目安。3つの観点(勾配の流れ・滑らかさ・自己ゲーティング)で違いを捉えると判断しやすくなります。

活性化関数の選択は、重み初期化・正規化・最適化と並ぶ「学習を安定させる4本柱」の一つです。次のステップとして、以下の記事も参考にしてください。