AIって結局何なのかよく分からないので、とりあえず100日間勉強してみた Day50
経緯についてはこちらをご参照ください。
■本日の進捗
- 多層パーセプトロンを理解
■はじめに
今回も「ゼロから作るDeep Learning Pythonで学ぶディープラーニングの理論と実装(オライリー・ジャパン)」で、深層学習を学んでいきます。
前回、ANDやNAND, ORといった論理ゲートを単純パーセプトロンで実装できることを学びました。では、単純パーセプトロンを用いればどんな複雑な論理ゲートも表現できるのでしょうか。
■排他的論理和
ここまで、0か1からなる2つの入力と1つの出力を持つ論理ゲートについて、入力値が2つとも1なら1を返すANDゲート、入力値が2つとも1でなければ1を返すNANDゲート、入力値どちらかが1なら1を返すORゲートを見てきました。
実はもう少し複雑な論理ゲートであるXORゲート(排他的論理和)なるものが存在します。これは、2つの入力値が異なる時だけ1を返す論理演算を行います。
$$\mathrm{Input} : x_1$$ | $$\mathrm{Input} : x_2$$ | $$\mathrm{Output} : y$$ |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
■単純パーセプトロンの限界
これをパーセプトロンで実現するためにはどうすれば良いのでしょうか。
ヘヴィサイド階段関数を用いた単純パーセプトロン
$$ \begin{eqnarray} H(x) = \begin{cases} 0 & (x \lt 0 ) \\ 1 & (x \gt 0 ) \end{cases} \end{eqnarray} $$
$$ y = H( w_1 x_1 + w_2 x_2 + b) $$
先程の真理表を眺めると分かりますが、XORゲートは単純パーセプトロンでは表現することはできません。つまり1次関数では表現できない演算ということです。これは単純パーセプトロンの限界と言われ、これが指摘された当初は一時的にパーセプトロンの研究が下火になるほどの影響があったとのことです。
(機械学習においての本質的な解決ではないのですが)XORゲートはこれまで出てきた論理ゲートを用いて表現することができ、表現は何通りかあるのですが、ここでは上記の単純パーセプトロンの式に置き換えられるように仮にs1とs2を導入して下記のようにおいてみます。
$$ y_{\mathrm{xor}} = H( w_1 s_1 + w_2 s_2 + b) $$
ANDゲートは入力値が2つとも1なら1を返す比較的シンプルな挙動なので、まずはANDゲートを導入して考えてみます。
$$ y_{\mathrm{and}} = H( w_1 x_1 + w_2 x_2 + b) \ \ \ ただし、w_1=1, \ w_2=1, \ b=-1.5 $$
入力が異なる時に1を返してくれるのはNANDとORでしたが、入力がどちらも1の時に0を返す(つまりANDに対する入力値のひとつとするとANDは必ず0を返す)NANDと、入力がどちらも0の時に0を返す(同様にこれをANDの入力値とするとANDが0を返す)ORを組み合わせるとXORを表現できそうです。
$$ y_{\mathrm{nand}} = H( w_1 x_1 + w_2 x_2 + b) \ \ \ ただし、w_1=-1, \ w_2=-1, \ b=1.5 $$
$$ y_{\mathrm{or}} = H( w_1 x_1 + w_2 x_2 + b) \ \ \ ただし、w_1=1, \ w_2=1, \ b=-0.5 $$
以上から、
$$ y_{\mathrm{xor}} = H( w_1 s_1 + w_2 s_2 + b) \ \ \ ただし、w_1=1, \ w_2=1, \ b=-1.5 $$
$$ s_1 = H( w_1 x_1 + w_2 x_2 + b) \ \ \ ただし、w_1=-1, \ w_2=-1, \ b=1.5 $$
$$ s_2 = H( w_1 x_1 + w_2 x_2 + b) \ \ \ ただし、w_1=1, \ w_2=1, \ b=-0.5 $$
■多層パーセプトロン
先ほど導出した式を実装してみて、正しくXORゲートを表現できているかを見てみます。前回同様に単位階段関数を用いています。
import numpy as np def SimplePerceptron(x1, x2, w1, w2, b): x = np.array([x1, x2]) w = np.array([w1, w2]) result = np.sum(w*x) + b return result def StepFunction(x): if x <= 0: return 0 else: return 1 def AND(x1_and, x2_and): result_and = SimplePerceptron(x1_and, x2_and, 1, 1, -1.5) y_and = StepFunction(result_and) return y_and def NAND(x1_nand, x2_nand): result_nand = SimplePerceptron(x1_nand, x2_nand, -1, -1, 1.5) y_nand = StepFunction(result_nand) return y_nand def OR(x1_or, x2_or): result_or = SimplePerceptron(x1_or, x2_or, 1, 1, -0.5) y_or = StepFunction(result_or) return y_or def XOR(x1_xor, x2_xor): result_s1 = NAND(x1_xor, x2_xor) result_s2 = OR(x1_xor, x2_xor) result_xor = AND(result_s1, result_s2) y_xor = StepFunction(result_xor) return y_xor print("When x1 = 0, x2 = 0") print("XOR: y={}".format(XOR(0, 0))) print("") print("When x1 = 0, x2 = 1") print("XOR: y={}".format(XOR(0, 1))) print("") print("When x1 = 1, x2 = 0") print("XOR: y={}".format(XOR(1, 0))) print("") print("When x1 = 1, x2 = 1") print("XOR: y={}".format(XOR(1, 1))) print("")
When x1 = 0, x2 = 0
XOR: y=0
When x1 = 0, x2 = 1
XOR: y=1
When x1 = 1, x2 = 0
XOR: y=1
When x1 = 1, x2 = 1
XOR: y=0
どうやらXORを実装できたみたいです。
今回、入力からXORの出力を得るまでに2回(全体では3回だが、ある1つの入力ニューロンから考えると2回)の単純パーセプトロンの処理を通っていることが分かります。つまり、XORのような非線形な挙動を単純パーセプトロンで記述することはできませんでしたが、2回重ねることで非線形表現ができるようになったということです。これを層が複数重なっていることから、多層パーセプトロン(MLP:multilayer perceptron)と言います。
■おわりに
単純パーセプトロンでは対応できない問題と、複数の層を重ねる多層パーセプトロンを導入することで複雑な表現ができるようになることが分かりました。
■参考文献
- Andreas C. Muller, Sarah Guido. Pythonではじめる機械学習. 中田 秀基 訳. オライリー・ジャパン. 2017. 392p.
- 斎藤 康毅. ゼロから作るDeep Learning Pythonで学ぶディープラーニングの理論と実装. オライリー・ジャパン. 2016. 320p.
- ChatGPT. 4o mini. OpenAI. 2024. https://chatgpt.com/
- API Reference. scikit-learn.org. https://scikit-learn.org/stable/api/index.html