人工ニューロン (Artificial Neuron)
神経細胞のモデル化
前回記事で扱った生物の神経細胞(ニューロン)の機能になぞらえて、コンピュータ上に「複数の信号を受け取り、適当な重み(荷重)を加えて足し合わせて、活性化関数によって強度を調整して出力する」という関数を設計します。
このようなモデルを 人工ニューロン (Artificial Neuron) とよびます。
「人工」をつけているのは、もちろん本物のニューロンと区別するためですが、機械学習の分野では単に「ニューロン」とよぶのが一般的です。
説明を簡単にするために、$2$つの信号 $(x_0,x_1)$ が入力される次のような人工ニューロンを考えます。
それぞれの入力信号を重み $w_0,\ w_1$ を掛けて足し合わせ、さらにバイアスパラメータ $w_2$ を加えた値 $u$ を、このニューロンに対する入力総和とよびます。
\[u=w_0x_0+w_1x_1+w_2\]
線形基底関数モデルのときと同じように、常に $1$ の値をとるような疑似信号 $x_2$ を導入して、入力総和を
\[u=w_0x_0+w_1x_1+w_2x_2\]
と書くことにすると、$2$つのベクトル
\[\boldsymbol{w}=\begin{bmatrix}w_0\\w_1\\w_2\end{bmatrix},\quad\boldsymbol{x}=\begin{bmatrix}x_0\\x_1\\x_2\end{bmatrix}\]
の内積を使って、
\[u=\boldsymbol{w}\cdot\boldsymbol{x}\]
と表すことができます。入力総和を活性化関数 $f(x)$ に通すことによって値を調整し、これをニューロンの出力 $y=f(u)$ とします。
\[y=f(u)=f(\boldsymbol{w}\cdot\boldsymbol{x})\]
単体ニューロンの実装
Python で単体の人工ニューロンを実装してみましょう。
活性化関数としては シグモイド関数 を採用します。
# Artificial_Neuron
# In[1]
import numpy as np
# シグモイド関数
def sigmoid(x):
f = 1 / (1 + np.exp(-x))
return f
# 人工ニューロン
def neuron(x, w):
u = np.dot(x, w)
y = sigmoid(u)
return y
neuron()関数には信号をいくつでも入力できますが、上にも述べたように、ベクトルの最後の成分はバイアスです。$N$ 個の信号を入力するモデルでは $N+1$ 個のベクトル成分が必要です。とりあえずは信号を $2$ 個にして、neuron() に $\boldsymbol{w}=(2,-1.5,0.2),\ \boldsymbol{x}=(1,2,1)$ を渡してみましょう。
# In[2]
# 重みを設定
w = np.array([2, -1.5, 0.2])
# ニューロンへの入力
x = np.array([1, 2, 1])
# ニューロンからの出力
y = neuron(x, w)
print(y)
# 0.31002551887238755
w や x の値を変えれば、出力は色々な値をとりますが、シグモイド関数を通しているので、必ず $0$ から $1$ の範囲に収まります。
$x_0$-$x_1$ 平面の上に $y=f(u)$ の値をプロットすれば、$x_0$ と $x_1$ の組合わせに応じた出力変化を可視化できます。matplotlib.pyplot と mpl_toolkits.mplot3d をインポートして、3Dグラフを描いてみましょう。
# In[3]
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 解像度を設定
xn = 33
# x0-x1平面上に格子点を作成
x0 = np.linspace(-1.0, 1.0, xn)
x1 = np.linspace(-1.0, 1.0, xn)
X0, X1 = np.meshgrid(x0, x1)
# x0,x1の重みを1.0,-1.0に設定
# バイアスの重みを0.2に設定
w = np.array([1.0, -1.0, 0.2])
# ニューロンの出力を格納する変数
Z = np.zeros((xn, xn))
# すべての格子点でニューロンからの出力を計算
for i in range(xn):
for j in range(xn):
Z[j][i] = neuron(w, [i, j, 1])
# FigureとAxesを追加
fig = plt.figure(figsize = (10, 6))
ax = fig.add_subplot(111, projection='3d')
# 軸ラベルを設定
ax.set_xlabel("x0", size = 16, labelpad = 10)
ax.set_ylabel("x1", size = 16, labelpad = 10)
ax.set_zlabel("y", size = 16)
# 曲面を描画
ax.plot_surface(X0, X1, Z, color = "green")
# 表示角度を設定
ax.view_init(45, 60)
plt.show()
これは見覚えのある図ですね。分類問題 で使用した2変数 ロジスティック関数 のグラフです。入力総和 $u$ は $x_0$ と $x_1$ の線形結合なので、それをシグモイド関数に渡せば、$x_0$ と $x_1$ を変数とするロジシティック関数になります。一般に $x_0,\ x_1,\ \cdots,\ x_{N-1}$ の入力があれば $N$変数ロジシティック関数を計算することになります。次回記事では数個のニューロンをつないで小さなニューラルネットワークを作って出力の様子を調べてみます。
In[3] プロクラムの下の文で、ロジスティック関数のリンク先が「シグモイド関数」の記事に
なっていますので、ご確認ください。
リンクを修正しておきました。
ありがとうございます。m(_ _)m