シグモイド関数とロジスティック関数

シグモイド関数とロジスティック関数

シグモイド関数

 シグモイド関数 (Sigmoid function)
 
\[f(x)=\frac{1}{1+e^{-ax}}\quad (a\gt 0)\]
によって定義され、ニューラルネットワークにおいてニューロンの特性を表す関数として登場します。Matplotlib と NumPy を使って $a$ を変化させながらグラフを描いてみます。

# リストA-1
# シグモイド関数のグラフを描画

# NumPyとMatplotlibをインポート
import numpy as np
import matplotlib.pyplot as plt

# シグモイド関数を定義
def sigmoid(x, a):
    return 1 / (1 + np.exp(-a * x))

# フィギュアを設定
fig = plt.figure()

# グラフ描画領域を追加
ax = fig.add_subplot(111)

# グリッド線を表示
ax.grid(linestyle = "--")

# グラフタイトルを設定
ax.set_title("Sigmoid Function", fontsize = 16)

# x軸, y軸のラベルを設定
ax.set_xlabel("x", fontsize = 16)
ax.set_ylabel("y", fontsize = 16)

# -10~10,256分割の点
x = np.linspace(-10, 10, 256)

# シグモイド関数をプロット
a = [0.5, 1, 4]
for k in range(3):
    y = sigmoid(x, a[k])
    ax.plot(x, y, label = "a = {}".format(a[k]))

# 凡例を表示
ax.legend()

plt.show()

 Python シグモイド関数グラフ

 シグモイド という名称は、曲線の形がギリシャ文字の $\varsigma$ (シグマ) に似ていることに由来します。$a$ はゲイン (gain) とよばれるパラメータです。図にあるように、$a$ が大きくなるほど原点付近の傾斜は大きくなって階段関数に近づいていきます。特にゲイン $a$ が $1$ のときは標準シグモイド関数とよばれます。シグモイド関数は微分方程式
 
\[\frac{dy}{dx}=ay(1-y)\]
を $y(0)=1/2$ の初期条件で解いて得られます。シグモイド関数を微分してみれば、この方程式を満たしていることはすぐにわかりますが、ここでは微分方程式を解いて一般解も確認しておきましょう。上式を変数分離すると
 
\[\frac{dy}{y(1-y)}=adx\]
となります。左辺を分解すると
 
\[\left(\frac{1}{y}+\frac{1}{1-y}\right)dy=adx\]
 両辺を積分すると
 
\[\begin{align*}
\log|y|-\log|1-y|&=ax+C\\[6pt]
\log\left|\frac{y}{1-y}\right|&=ax+C\\[6pt]
\frac{y}{1-y}&=\pm e^{ax+C}\\[6pt]\end{align*}\]
 $A=\pm e^C$ とおいて式を整理すると、
 
\[y=\frac{A}{A+e^{-ax}}\]
が得られます。初期条件 $y(0)=1/2$ を代入すると $A=1$ が決まるので、
 
\[y=\frac{1}{1+e^{-ax}}\]
となってシグモイド関数が現れます。手作業で微分方程式を解くのが面倒であれば、以下のように SymPyパッケージをインポートして解く方法もあります(微分方程式の解き方についてはこちらの記事を参照してください)。

# リストB-1
# シグモイド関数 (Jupyter Notebook用コード)

# SymPyをインポート
import sympy

# MathJaxで表示
sympy.init_printing()

# 記号x,y,C1を定義
sympy.var('a x y C1')

# 微分方程式 dy/dx = ay(1 - y)
eq = sympy.Eq(y(x).diff(x), a*y(x)*(1 - y(x)))

# 微分方程式の一般解
ys = sympy.dsolve(eq)

display(ys)
\[y{\left (x \right )} = - \frac{1}{C_{1} e^{-ax} - 1}\]

 

ロジスティック関数

 次式で定義される ロジスティック関数 (Logistic function) はシグモイド関数を特別な形として包む、より汎用的な関数です。
 
\[N=\frac{K}{1+\exp\left\{-aK(x-x_0)\right\}}\]
 この定義式において $K=1,\ x_0=0$ とすれば、シグモイド関数となります。シグモイド関数は(パラメータ $a$ によって)曲線の形しか変えられませんでしたが、ロジスティック関数は $x_0$ によって左右に平行移動させることが可能です。そのため、機械学習の分類問題の回帰手法として用いられることがあります。次のコードは $a=1,\ K=1$ として、$x_0$ を変化させてロジスティック関数をプロットします。

# リストC-1
# ロジスティック関数のグラフ

# モジュールをインポート
import numpy as np
import matplotlib.pyplot as plt

# ロジスティック関数を定義
def logistic(x, a, k, x0):
    y = k / (1 + np.exp(-a * k * (x - x0)))
    return y

# FigureとAxesの設定
fig = plt.figure()
ax = fig.add_subplot(111)
ax.grid(linestyle = "--")
ax.set_title("Logistic Function", fontsize = 16)
ax.set_xlim(-8, 10)
ax.set_xlabel("x", fontsize = 16)
ax.set_ylabel("y", fontsize = 16)

# xのデータ
x = np.linspace(-10, 10, 256)

# x0を変えながらロジスティック関数をプロット
x0 = [0, 2, 4]
for j in range(3):
    y = logistic(x, 1, 1, x0[j])
    ax.plot(x, y, label = "x0 = {}".format(x0[j]))

ax.legend()

Python ロジスティック関数