ReLU (Rectified Linear Unit)
ReLU(正規化線形ユニット)はmax(0, x)を出力し、正の入力をそのまま通し、負の入力をゼロにします。勾配、Dying ReLU、派生手法、PyTorchコードを解説します。
整流線形ユニット(ReLU)は、f(x) = max(0, x)で表される活性化関数です。正の入力はそのまま通し、それ以外にはゼロを出力します。この単純な比較処理によって、ニューラルネットワーク(NN)は、ほとんど計算コストをかけずに、曲線状のパターンを学習するための非線形性を得られます。Vinod NairとGeoffrey Hintonが2010年にReLUを使用し、ReLUを採用した畳み込みニューラルネットワーク(CNN)であるAlexNetが2012年のImageNetチャレンジで優勝したことを受け、ReLUはディープラーニングの隠れ層における標準的な活性化関数になりました。SiLUやGELUなど新しい活性化関数の評価基準として、今も使われています。
ReLUの仕組み#
ReLUの導関数は、正の入力で1、負の入力で0です。ちょうど0では導関数は定義されませんが、PyTorchなどのフレームワークでは0を使います。この2つの値から、ReLUの主な特性が分かります。
- 計算コストが低い: フォワードパスではゼロとの比較、バックワードパスではマスク処理を行うだけで、シグモイドやtanhのような指数関数の計算は不要です。
- 正の入力では飽和しない: 勾配が厳密に1のため、活性化しているユニットを通る勾配はそのまま維持されます。そのため、飽和関数が引き起こす勾配消失問題のように、多数の層を逆向きに伝わる誤差信号が縮小しません。
- スパースな活性化: 負の入力はすべて厳密にゼロになるため、各時点で層の一部のみが活性化します。重みをランダムに初期化した場合、特定の入力に対して層内のユニットの約半数がゼロを出力します。
- 区分線形: ReLUで構成されたネットワークは、入力に対する区分線形関数を計算します。多数の線形領域が、ユニットのオン・オフが切り替わる点でつながっています。
次のPyTorchの例では、nn.ReLUを適用し、autogradを使って同じ点での勾配を計算します。
import torch
from torch import nn
relu = nn.ReLU()
# Inputs on both sides of zero, tracked so PyTorch can compute gradients
x = torch.tensor([-2.0, -0.5, 0.0, 0.5, 2.0], requires_grad=True)
y = relu(x)
# Backpropagate a gradient of 1 from each output to its input
y.sum().backward()
print(f"Output: {y.tolist()}")
print(f"Gradient: {x.grad.tolist()}")出力[0.0, 0.0, 0.0, 0.5, 2.0]と勾配[0.0, 0.0, 0.0, 1.0, 1.0]を表示します。正の入力は勾配を保ったまま通過し、負の入力とゼロには勾配がまったく与えられません。これがReLUのスパース性と、主な失敗要因の両方の源です。
ReLUのニューロンが死ぬ問題#
トレーニングデータのすべての例で入力が負になるReLUユニットは、ゼロを出力して勾配もゼロになるため、重みが二度と変化せず、実質的に機能停止します。多くの場合、高い学習率などが原因で大きな重み更新が起き、バイアスが大幅に負の値になることでユニットが機能停止します。機能停止したユニットが少数なら影響は小さい一方、適切に調整されていない実行では層の大部分が機能停止することがあります。ReLU層向けに初期重みをスケーリングするHe初期化に、適度な学習率とバッチ正規化を組み合わせると、大部分のユニットを動作状態に保てます。また、Leaky ReLUなどの変種では勾配がゼロにならないため、この問題を解消できます。
ReLUの変種#
- Leaky ReLU: 負の入力に小さな固定傾斜(通常0.01)を掛けるため、非活性のユニットにも勾配が与えられます。
- PReLU: トレーニング中に負の傾斜を学習します。Kaiming Heらが2015年に、He初期化を提案した論文と同じ論文で発表しました。
- ReLU6: 出力を6で上限処理します。式はmin(max(0, x), 6)です。これにより、低精度演算で適切に表現できる範囲に活性化値を収めます。MobileNetV1とMobileNetV2で使われています。
- ELU: 負の領域を、−1に漸近する滑らかな指数曲線に置き換え、平均活性化値をゼロに近づけます。
- SiLUとGELU: x · σ(x)とx · Φ(x)で表される滑らかな曲線です。大きな入力ではReLUのように動作しますが、小さな負の値も通し、ゼロに折れ曲がりがありません。要素あたりの計算コストは高くなりますが、GELUの論文では、評価したすべてのビジョン、言語、音声タスクでReLUを上回る性能が報告されました。
ReLUとシグモイド・tanhの比較#
ReLU以前は、隠れ層にシグモイドやtanhが使われていました。どちらも飽和する関数です。大きな正または負の入力では曲線が平坦になり、導関数がゼロに近づきます。シグモイドの導関数は、最も傾斜が急な点でも0.25を超えません。このような導関数を多数の層にわたって掛け合わせると、初期層に勾配がほとんど届かなくなります。AlexNetの論文では、ReLUを使う4層CNNが、tanhユニットを使う同じネットワークより6倍速く、CIFAR-10のトレーニングエラー率25%に到達しました。シグモイドとtanhは、値域が制限されていること自体が重要な用途で今も使われています。シグモイドは確率を表す出力層や再帰セルのゲートに、tanhは再帰型ネットワークの隠れ状態に使われます。
最新モデルにおけるReLU#
ResNetや同時代のほとんどのCNNは、全層でReLUを使います。2017年の初代Transformerも、フィードフォワード層でReLUを使っていました。近年は、BERTやビジョンTransformerではGELU、多くの最新大規模言語モデルではSwiGLUなど、より滑らかな関数に切り替えるモデルが増えています。一方、速度やハードウェアサポートが重要な場面では、今もReLUが一般的です。YOLO26はデフォルトでConvブロックにSiLUを使いますが、モデルYAMLのactivation: nn.ReLU()行を設定すると、トレーニング前にすべてのConvブロックでReLUが使われます。これはSiLUには対応せず、ReLUをネイティブに実行するAMD Zynq UltraScale+ DPUなどのアクセラレーターに適しています。PyTorchでは、nn.ReLU(inplace=True)は入力テンソルを結果で上書きし、別の出力テンソルに必要なメモリーを節約します。










