Deep Learningについての基礎を教えていると、「活性化関数が何者かよくわからん」と多くの人が学習の最初の躓きポイントになった人が結構います。
入力と重みを行列の掛け算をして~、重みに従って入力が活かされる値が調整されて~、バイアスで調整して~
と、その辺りは高校数学の行列の知識で「なんかうろ覚えだけど言いたいことはわかる」とあまり躓くことはないのですが、
こいつにいきなり「活性化関数」がかけられます。
こいつは何者なんだと
恐らく最初はステップ関数やSigmoid関数が紹介されて「あ、値を0.0~1.0に丸める奴なのかな」と思っていたら
ReLU関数などが登場して全然違う形状の関数が登場した日には
結局なんなんだこれは、wikipediaにもいろいろ書いてあるけどわからんぞ、となってしまいます。
もちろん「よくわからんけどニューラルネットワークの儀式的なものなんだな」であきらめてしまっても良いのですが、それぞれの意味付けを理解しながら学習する人にとっては最初の関門じゃないかと思います。
A.言葉が悪い
活性化関数の説明で表現力をあげる、とか、分類問題の場合はSigmoid/Softmaxを使うという説明を受けて
「よくわからん、何故?」という疑問をもっている人は非常に正しいです。
隠れ層における「活性化関数」と出力層における「活性化関数」は全く役割が異なります。
私の個人的な意見ですが同じ言葉を使うのをやめてほしいとすら思っています。
この区別をせずに説明を受けるので「よくわからん」となってしまうのではないかと思います。
これから学習する人は単に「活性化関数」としてとらえるのではなく、
「隠れ層における活性化関数」と「出力層における活性化関数」は完全に別物であると捉えて学習した方が良いと思います。
-
出力層の活性化関数 は、モデルの計算結果を タスクが求める「出力形式」に変換する 役割。
-
隠れ層の活性化関数 は、モデルが複雑なパターンを学習できるように 「表現力」 を高める
この2つの違いを意識するだけで、理解度がグッと深まります。では、それぞれを詳しく見ていきましょう。
※実際は出力層における活性化関数も表現力向上の役割がありますが、ここでは理解の区別ため役割を二極化して説明します
① 出力層の活性化関数:タスクが求める「出力形式」に変換する役割
出力層は、ニューラルネットワークの最終的な答えを出す部分です。ここでの活性化関数は、それまでの計算結果を 「人間が解釈しやすい形式」や「タスクが求める形式」に変換する 役割を持ちます。
どんなタスクを解きたいかによって、使う変換方法(活性化関数)が変わります。
タスク例1:家の値段を予測する(回帰)
- 目的: 5000万円、1億2000万円のような具体的な数値を予測したい。
- 使う活性化関数: 恒等関数
- 役割: 何もしません。計算された数値をそのまま出力します。予測したいものが数値そのものなので、特別な変換は不要です。
タスク例2:「スパムメールかどうか」を判定する(二値分類)
- 目的: スパムである確率を0〜1(例: 0.8なら80%)で示したい。
- 使う活性化関数: Sigmoid関数
- 役割: どんな数値が来ても、強制的に0〜1の間の確率に変換します。これにより「〇〇である確率」として解釈できる値になります。つまりニューラルネットワークが計算で「スパム度 251」とかいう俺俺ルールのスコアを出してくるので、それを「251→80%」と0~100%の値に丸めてくれるのがSigmoid関数です。
タスク例3:「犬・猫・鳥」のどれかを当てる(多クラス分類)
- 目的: 「犬: 70%, 猫: 20%, 鳥: 10%」のように、全選択肢の合計が1(100%)になる確率のリストで示したい。
- 使う活性化関数: Softmax関数
- 役割: 出力された複数の数値を、合計すると1になる確率のリストに変換します。これにより、最も確率の高いものをモデルの最終的な答えとして選ぶことができます。
このように、 出力層の活性化関数 は 「解きたい問題に合わせて、最終的な答えのフォーマットを整える」 のが仕事です。
② 隠れ層の活性化関数:モデルの「表現力」を高める役割
隠れ層(中間層)は、入力された情報から複雑な特徴を捉える、モデルの心臓部です。ここでの活性化関数の役割は、 モデルに「非線形性」を導入し、表現力を高めること です。
なぜ「表現力」を高める必要がある?
もし活性化関数がないと、ニューラルネットワークはただの「線形変換」の繰り返しになってしまいます。
線形変換とは、ざっくり言うと「まっすぐな変換」のことです($y=ax$のような一次関数をイメージしてください)。そして、線形変換は何度繰り返しても、結局は1回の線形変換と同じことしかできません。
これでは、層を深くする意味がありません。まっすぐな処理しかできないので、現実世界にあるような複雑なパターン(曲線的な関係)を学習することができないのです。
そこで活性化関数の出番です。
線形変換の間に活性化関数を挟むことで、処理が「カクン」と折れ曲がります(非線形な変換)。この非線形な変換を何度も繰り返すことで、ニューラルネットワークはどんなに複雑なグニャグニャした関数でも表現できるようになります。これが表現力の向上です。
隠れ層のデファクトスタンダード:ReLU
現在、隠れ層で最もよく使われるのが ReLU(Rectified Linear Unit) です。
- 役割: 入力が0以下なら0を返し、0より大きければその値をそのまま返す。
- 数式: $f(x) = \max(0, x)$
ReLUは非常にシンプルな関数ですが、この「0でカクンと折れ曲がる」という性質が、ニューラルネットワークに強力な非線形性を与えます。また、計算が非常に高速です。
もちろんSigmoid関数なども隠れ層の活性化関数として使用できます。
実際2015年以前はSigmoid関数が標準的に使われていました。今でもニューラルネットワークの基礎説明のためにはSigmoid関数で説明していることが多いと思います。
ここで出力層も隠れ層も同じSigmoid関数なので理解がごっちゃになりやすいと個人的に思っています。
同じSigmoid関数でも隠れ層と出力層では役割が違うと理解した方がよいです
しかし勾配消失問題という問題が発生するため、ReLU(及びその派生関数)が現在の標準的な選択肢となっています。
(勾配消失に関しては次のステップである損失関数、最適化関数あたりで登場します。)
ですので「中間層はReLUでなくてはいけない」ではなく「表現力があがる奴なら何でもいいけど、ReLUが成績が良い」という理解でよいです。
逆に出力層はReLUを使うことはまずありません、前述の通り出力層における活性化関数は「タスクが求める形」にデータを整形する意味も持っているのでReLUのような形の出力を求めることはそうないと思います。
まとめ
-
隠れ層の活性化関数と出力層の活性化関数は役割が別物と考えた方が良い
これをごっちゃに説明されるのでよくわからなくなる。 -
役割はこんな感じ
出力層の活性化関数 | 隠れ層の活性化関数 | |
---|---|---|
役割 | 最終出力をタスクに適した形式に変換する | モデルの表現力を高める(非線形化) |
選び方 | タスク(出力の形) に合わせて決める。決め打ち。 | 割と何でも良いが、実績的にReLUがよく選択される |
※本記事では初学者向けに役割を単純化二極化して解説しましたが。
実際には、出力層の活性化関数も表現力向上に寄与しています。逆伝播における勾配計算に直接影響するため、単なる形式変換だけでなく学習の安定性や効率を左右する役割を担っています。