活性化関数(Activation Function)の動きを理解する【初級 深層学習講座】
![](https://tech.aru-zakki.com/wp-content/uploads/2024/01/activation-function.001.jpeg)
この記事では、ディープラーニングの理解に必要となる、活性化関数の動きについて解説します。活性化関数について知りたい方は読んでみてください。
活性化関数(Activation Function)とは
ニューラルネットワークの活性化関数(Activation Function)は、各ニューロンが入力を受け取ってその出力を生成する際に使用される関数です。
この関数は、ニューロンの活性化状態を制御し、ネットワークが非線形な表現を学習できるようにします。
活性化関数は非線形であることが特徴で、非線形性がないと、ニューラルネットワークは複雑なパターンを学習するのが難しくなります。
![](https://tech.aru-zakki.com/wp-content/uploads/2023/06/tabbycat.png)
非線形性がない場合、ニューラルネットワークは単純な線形変換しか学習できません。これは、ネットワークが複雑なパターンや非線形な関係を理解するのが難しくなります
![](https://tech.aru-zakki.com/wp-content/uploads/2023/07/cat2-e1688625674820.png)
下図のように、線形だと直線でしか分離できないですが、非線形だと曲線で分離できるようになりますね
![](https://tech.aru-zakki.com/wp-content/uploads/2024/01/image-1024x514.png)
![](https://tech.aru-zakki.com/wp-content/uploads/2023/06/tabbycat.png)
非線形な関数を途中に挟むことで、複雑な分類を学習できるようにしているわけです。
代表的な活性化関数
数十年前は、シグモイドとTanh関数くらいしか活性化関数はありませんでしたが、最近はいろいろな活性化関数が提案され、活用されています。
ここでは、よく使われる活性化関数をいくつか解説します。確認用のコードも合わせて書いています。動かすには、以下のライブラリをインポートしてください。
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
シグモイド(Sigmoid)
入力を0から1の範囲に変換する活性化関数です。昔から使われている活性化関数ですが、勾配消失の問題があるため、最近は他の活性化関数を使うことが多いです。
![](https://tech.aru-zakki.com/wp-content/uploads/2023/06/tabbycat.png)
勾配消失とは、微分値がゼロに近くなることです。シグモイドの場合は、値が大きく(小さく)なると勾配がゼロに近づきます。
![](https://tech.aru-zakki.com/wp-content/uploads/2023/07/cat2-e1688625674820.png)
最終段で、出力を0~1にするために使われることはありますね
x = torch.linspace(-5, 5, 100)
y = nn.Sigmoid()(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title("Sigmoid")
plt.grid()
plt.show()
グラフは、横軸が入力値(x)、縦軸が出力値(y)です。シグモイドの場合、大きな値(小さな値)は1(0)に近づく以下のようなグラフになります。
![sigmoid](https://tech.aru-zakki.com/wp-content/uploads/2024/01/image-2.png)
ハイパボリックタンジェント(Tanh)
入力を-1から1の範囲に変換します。シグモイド関数に似ていますが、出力範囲が-1から1と異なります。この関数も勾配消失の問題があります。
x = torch.linspace(-5, 5, 100)
y = nn.Tanh()(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title("tanh")
plt.grid()
plt.show()
![tanh](https://tech.aru-zakki.com/wp-content/uploads/2024/01/image-1.png)
ReLU
2000年代に入り、ReLUが提案されました。計算効率が高く、勾配消失の問題を軽減できることが特徴で、ディープラーニング(深層学習)では最近もよく利用されています。
ReLUでは、入力がゼロより大きい場合はそのまま、ゼロ以下の場合はゼロとなる以下のような式になります。
$$
ReLU(x) = max(0, x)
$$
式から分かるように$$x=0$$が特異点となります。また、$$x < 0$$については勾配が常に0になるため、勾配消失の問題が発生する可能性があります。
x = torch.linspace(-5, 5, 100)
y = nn.ReLU()(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title("ReLU")
plt.grid()
plt.show()
![ReLU](https://tech.aru-zakki.com/wp-content/uploads/2024/01/image-3.png)
LeakedReLU
ReLUの改良版で、ゼロ以下の領域で微小な傾きを持ちます。これにより、ゼロ以下の入力でも微小な勾配が伝播し、一部のタスクではReLUよりも優れた性能を発揮します。
x = torch.linspace(-5, 5, 100)
y = nn.LeakyReLU()(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title("LeakyReLU")
plt.grid()
plt.show()
![ReakyReLU](https://tech.aru-zakki.com/wp-content/uploads/2024/01/image-4.png)
![](https://tech.aru-zakki.com/wp-content/uploads/2023/06/tabbycat.png)
グラフではわかりにくいですが、0以下が僅かに傾斜しています
GELU
GELUは、GPTやBERT(Bidirectional Encoder Representations from Transformers)などの自然言語処理タスクで利用されている活性化関数です。
ReLUに比べて0付近で滑らかな形状を持ちます。
x = torch.linspace(-5, 5, 100)
y = nn.GELU()(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title("GELU")
plt.grid()
plt.show()
![GELU](https://tech.aru-zakki.com/wp-content/uploads/2024/01/image-5.png)
Mish
ReLUの改良版にSwishという活性化関数がありますが、Swishの改良版がMishになります。
ReLUやSwishよりもなめらかで、勾配消失の問題に対処することができるとされています。
x = torch.linspace(-5, 5, 100)
y = nn.Mish()(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title("Mish")
plt.grid()
plt.show()
![MISH](https://tech.aru-zakki.com/wp-content/uploads/2024/01/image-6.png)
どの活性化関数が良いの?
計算効率が高いのはReLU
勾配消失の問題を緩和し、かつ、計算効率が高いのがReLUです。個人的には、とりあえず、ReLUで組んでみることも多いです。
タスクに応じて選ぶ
タスクによって適した活性化関数は違います。自然言語処理でGELUが使われていますし、他のタスクでは違った活性化関数の方がよいこともあります。
まずは、ターゲットとするタスクでよく使われている活性化関数を調べてみましょう。
結局、評価してみるしかない
結局、活性化関数を変えて評価実験するのが一番良いと思います。Pytorchの場合、活性化関数を変更するのは比較的簡単です。
ハイパーパラメーターの調整の1つとして、活性化関数の評価も行ってみるべきです。
まとめ
以上、活性化関数について簡単にまとめました。