ディープラーニングの参考書などを読んでいると、よく「パーセプトロン」という言葉が出てきます。
今回は機械学習の基礎としてパーセプトロンの特徴や限界、Pythonでの実装方法についてまとめてみました。
この記事を書いている僕はシステムエンジニア6年目
普段はJavaでWebアプリを作ったりSQL書いたり・・・、
なので最近流行りのPython、数学、人工知能、デープラーニングができる人には正直憧れています。。。。
自分も一から勉強してこの辺りできるようになりたい、、画像認識モデルを作ったりして、アプリに組み込みたい!
これが機械学習、深層学習の勉強を始めたきっかけでした。
体系的に、この分野の基礎から学ぼうとJDLAのG検定の勉強をして合格するところまでいきました。
次のステップとして、
実際にPythonでコードを書きながら機械学習や深層学習の知識を深めているところです。。。
今回は、G検定で勉強した内容と、機械学習の参考書を色々勉強していく中で重要だと感じた、
「パーセプトロン」についてまとめてみました。
JDLAのG検定の出題範囲なのでG検定合格を目指している方にもオススメです。
パーセプトロン
パーセプトロンの仕組み
まず、機械学習の教材などでよく見る図ですが、、
パーセプトロンを絵にしたものを確認してみましょう。
丸で囲まれた\( x_1\)や\( x_2\)、そして\( y\)は「ニューロン」や「ノード」と呼びます。
\( x_1\)、\( x_2\)は入力信号で、ここから入力値が入ります。
\( w_1\)、\( w_2\)が重みで、入力信号はそれぞれ重みが乗算されて次のニューロン\( y\)に到達します。
つまり、ニューロン\( y\)には\( x_{1}w_{1}\)と\( x_{2}w_{2}\)の信号がそれぞれ送られてきます。
ニューロン\( y\)では送られた信号の総和が計算され、その総和が閾値(限界値)を超えた場合のみ1を出力します。
以上を数式で表すと以下のようになります。
閾値を\( \theta\)とする
$$ \begin{eqnarray}y = \begin{cases} 0 & ( w_{1}x_{1} + w_{2}x_{2} \leq \theta) \\ 1 & ( w_{1}x_{1} + w_{2}x_{2} \gt \theta) \end{cases}\end{eqnarray} $$
具体的な値を入れてみると以下の図のようになります。
上の例では\( w_{1}\)、\( w_{2}\)の重みをどちらも\( 0.5\)としましたが、入力信号の重要度をコントロールするパラメータとして機能します。
(\( x_{1}\)の方が重要な入力信号の場合、\( w_{1}\)を\( 0.7\)とするなど)
また、上のパーセプトロンで、\( x_1\)、\( x_2\)を変化させた際の\( y\)の出力をまとめた表が以下です。
\( x_1\) | \( x_2\) | \( y\) |
---|---|---|
0 | 0 | 0 |
1 | 0 | 0 |
0 | 1 | 0 |
1 | 1 | 1 |
例で挙げたパーセプトロンは論理回路のANDゲートと同じ出力になるものでした。
ちなみに、
\( w_1 = 0.5\)、\( w_2 = 0.5\)、\( \theta = 0.5\)にすればORゲートになり、
\( w_1 = -0.5\)、\( w_2 = -0.5\)、\( \theta = -0.6\)にすればNANDゲートになります。
パーセプトロンにバイアスの導入
パーセプトロンは非常にシンプルで理解しやすかったと思います。
次に先ほどのパーセプトロンの式において、閾値\( \theta\)を\( -b\)として式を変換します。
$$ \begin{eqnarray}y = \begin{cases} 0 & ( b + w_{1}x_{1} + w_{2}x_{2} \leq \theta) \\ 1 & ( b + w_{1}x_{1} + w_{2}x_{2} \gt \theta) \end{cases}\end{eqnarray} $$
\( b\)をバイアスと呼びます。
バイアスはニューロン\( y\)の発火のしやすさ(出力信号が1を出力する度合い)を制御します。
今後はバイアスを導入したこちらの式を使います。
では、今度はバイアスが導入されたパーセプトロンでを図ではなくpythonのソースコードで表現します。
# パーセプトロン
import numpy as np
def perceptron(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.6
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
print(" x1 | x2 | y ")
print(" 0 | 0 | ", perceptron(0, 0))
print(" 1 | 0 | ", perceptron(1, 0))
print(" 0 | 1 | ", perceptron(0, 1))
print(" 1 | 0 | ", perceptron(1, 0))
print(" 1 | 1 | ", perceptron(1, 1))
パーセプトロンの限界
ANDゲートをグラフにすると以下のようになります。
上のグラフは横軸\( x_1\)、縦軸\( x_2\)、
式は
$$ \begin{eqnarray}y = \begin{cases} 0 & ( -1.2 + x_{1} + x_{2} \leq \theta) \\ 1 & ( -1.2 + x_{1} + x_{2} \gt \theta) \end{cases}\end{eqnarray} $$
色が塗ってある領域(\( x_1 = 1\)、\( x_2 = 1\))が出力\( 1\)になります。
同じように、ORやNANDゲートを直線のグラフで表すことができます。
次にXORゲートについて考えてみます。
XORゲートの入出力は以下の表です。
\( x_1\) | \( x_2\) | \( y\) |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 0 |
XORをグラフで表すと以下になります。
先ほどのように緑の星マークと青のダイヤマークの領域を直線で分けることはできません。。
これがパーセプトロンの限界です。
パーセプトロンでは、1本の直線で領域を分ける(線形な領域)ことができないのです。
もし、1本の曲線で領域を分ける(非線形な領域)ことができるなら以下のように分けられますが、
パーセプトロンでは線形な領域を表現することしかできません。
多層パーセプトロン
パーセプトロンではXORゲートを表現できませんでした。
しかし、
実はパーセプトロンの層を以下のように重ねることで、
XORゲートが表現できます。
NANDの結果が\( s_1 \)となり、ANDの入力になります。
また、ORの結果が\( s_2 \)となり、ANDの入力になります。
入出力結果をまとめると以下の表のようになります。
\( x_1\) | \( x_2\) | \( s_1\) | \( s_2\) | \( y\) |
---|---|---|---|---|
0 | 0 | 1 | 0 | 0 |
1 | 0 | 1 | 1 | 1 |
0 | 1 | 1 | 1 | 1 |
1 | 1 | 0 | 1 | 0 |
また、上記をパーセプトロンの表記にすると以下のようになります。
このことから、
パーセプトロン単層では表現できなかったことが、
層を1つ増やすことで表現できるようになったと言えます。
ちなみにXORをPythonで書くと以下のようになります。
import numpy as np
def AND(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.7
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
def NAND(x1, x2):
x = np.array([x1, x2])
w = np.array([-0.5, -0.5])
b = 0.7
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
def OR(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.2
tmp = np.sum(w * x) + b
if tmp <= 0:
return 0
else:
return 1
def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y
print(" x1 | x2 | y ")
print(" --------------- ")
print(" 0 | 0 | ", XOR(0, 0))
print(" 1 | 0 | ", XOR(1, 0))
print(" 0 | 1 | ", XOR(0, 1))
print(" 1 | 1 | ", XOR(1, 1))
まとめ
ということで、今回はパーセプトロンについて確認してきました。
とてもシンプルなアルゴリズムなので理解は簡単だったと思います。
以下は重要なポイントなので、抑えておきましょう!
- パーセプトロンでは、「重み」と「バイアス」をパラメータとして手動で設定する
- パーセプトロンを用いれば、ANDやORゲートなどの論理回路を表現できる
- XORゲートのような非線形領域の表現は単層のパーセプトロンではできない
- パーセプトロンを複数の層繋げればXORゲートのような非線形領域も表現できる
参考にした資料