単純パーセプトロンによる論理回路(1)

単純パーセプトロンで、ANDゲート・NANDゲート・ORゲート・XORゲートを実装する。ただし、XORゲートは単層では実装できない。非線形領域は単純パーセプトロンで分離できないからだ。そこで、他の3種を組み合わせることで、XORゲートも実装する。

入力([x1, x2])は、

import numpy as np

X = np.array([
    [0, 0],
    [1, 0],
    [0, 1],
    [1, 1]
])

の4通りで、1が真(信号を流す)、0が偽(信号を流さない)に対応している。

出力(y)は、ANDゲートであれば、[x1, x2] = [1, 1]の場合のみ1で、その他は0になる。つまり、

Y = np.array([
    0,
    0,
    0,
    1
])

となる。

NANDゲートであれば、[1, 1]の場合のみ0で、その他は1になる。

Y = np.array([
    1,
    1,
    1,
    0
])

ORゲートであれば、[0, 0]の場合のみ0で、その他は1になる。

Y = np.array([
    0,
    1,
    1,
    1
])

XORゲートであれば、[1, 0], [0, 1]の場合に1で、その他は0になる。

Y = np.array([
    0,
    1,
    1,
    0
])

さて、単純パーセプトロンは、入力の加重総和にヘヴィサイドステップ関数を適用して出力する。

一般的には、出力層以外の層にバイアスニューロンをつけ加える。バイアスニューロンは、常に1を出力する特別なタイプのニューロンだ。これと次の層の接続部に与えられる重みのことをバイアスという。バイアス(b)は、ニューロンの発火のしやすさをコントロールし、その他の重み(w1, w2)は、各信号の重要性をコントロールする。

パラメータ(バイアスと重み)を適切に設定することで、AND・NAND・ORは実現できる。適切なパラメータの組み合わせは無限にある。

そして、XORゲートは、以下のような配線で実現できる。

Logic Gates by Perceptron

In [1]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
In [2]:
def heaviside_step(z):
    return np.where(z < 0, 0, 1)
In [3]:
x = np.arange(-5.0, 5.0, 0.1)
y = heaviside_step(x)
In [4]:
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()
In [5]:
class Perceptron:
    def  __init__(self, weights):
        self.weights = weights
        
    def output(self, input):
        return self.__activate(np.dot(input, self.weights[1:]) + self.weights[0])
    
    def __activate(self, weighted_sum):
        return self.__heaviside_step(weighted_sum)
    
    def __heaviside_step(self, z):
        return np.where(z < 0, 0, 1)
In [6]:
X = np.array([
    [0, 0],
    [1, 0],
    [0, 1],
    [1, 1]
])
In [7]:
and_gate = Perceptron(np.array([-0.7, 0.5, 0.5]))
out = and_gate.output(X)
out
Out[7]:
array([0, 0, 0, 1])
In [8]:
nand_gate = Perceptron(np.array([0.7, -0.5, -0.5]))
out = nand_gate.output(X)
out
Out[8]:
array([1, 1, 1, 0])
In [9]:
or_gate = Perceptron(np.array([-0.3, 0.5, 0.5]))
out = or_gate.output(X)
out
Out[9]:
array([0, 1, 1, 1])
In [10]:
class XOR:
    def __init__(self):
        self.and_gate = Perceptron(np.array([-0.7, 0.5, 0.5]))
        self.nand_gate = Perceptron(np.array([0.7, -0.5, -0.5]))
        self.or_gate = Perceptron(np.array([-0.3, 0.5, 0.5]))
        
    def output(self, input):
        nand_output = self.nand_gate.output(input)
        or_output = self.or_gate.output(input)
        and_input = np.vstack([nand_output, or_output]).T
        return self.and_gate.output(and_input)
In [11]:
xor_gate = XOR()
out = xor_gate.output(X)
out
Out[11]:
array([0, 1, 1, 0])

ソースコード

https://github.com/aknd/machine-learning-samples