🧠

【Python】単純パーセプトロンを理解する

2022/11/08に公開

初心に還ってパーセプトロンを実装します。

単純パーセプトロンがANDを学習している様子

パーセプトロンとは

1958年、Rosenblattによって提案されたネットワークモデル。
脳の中の生物学的なニューロンを単純化したモデルで、最も単純なニューラルネットワークです。
線形分離可能な問題であれば解くことができます。
ここではパーセプトロンの中でも単純パーセプトロンを取り扱います。

パーセプトロンは、ニューロンを次のようなステップでモデル化している。
(入力がn個で出力が1個のパーセプトロン)

  1. 入力信号を受け取る。(入力:x_i
  2. 入力の重み付きの和を計算(重み:w_i
  3. 2の結果にバイアスを足す(バイアス:b
  4. 3の結果をステップ関数に通して出力(ステップ関数:\phi

パーセプトロンの数式

重み付きの和+バイアス

z = \sum^{n}_{i=0} x_i w_i + b\\

ベクトル表記版

x = \begin{bmatrix} x_0\\ x_1\\ ...\\ x_n \end{bmatrix}; w = \begin{bmatrix} w_0\\ w_1\\ ...\\ w_n \end{bmatrix}\\ z = \bm{x} \cdot \bm{w} + b

ステップ関数

\phi(z) = \begin{cases} {1\ (z > 0)}\\ {0 \ (z \leq 0)} \end{cases}

パーセプトロンのコード

numpyを使えば簡単ですが、勉強のために使わずに実装してみます。

内積

def dot(A,B):
    return sum([a*b for a,b in zip(A,B)])

ステップ関数

def step_func(z):
    return 1 if z > 0 else 0

単純パーセプトロン

def predict(X,W):
    z = dot(X,W)
    return step_func(z)

学習方法

パーセプトロンは重みバイアスの値を変化せると、自由に形が変わる(もちろん線形にですが)ので、この重みとバイアスをモデルに合うように学習します。

  1. ある入力信号\bm{x}_cに対する出力と教師信号の差を求める。(教師信号:\bm{t}_c
  2. 2で求めた差に学習係数と入力をかける。(学習係数:\eta

重みの更新式

\Delta w_i = \eta(t_{ci} - z_{ci})x_{ci}

ベクトル表記版

\Delta \bm{w} = \eta(\bm{t}_{c} - \bm{z}_{c})\bm{x}_{c}

学習のコード

重みの更新

# 重みの変化量
def delta_weight(X, z, t, eta = 1):
    dW = []
    diff = t-z
    for x in X:
        dW.append(eta*diff*x)
    return dW
    
# 重みの更新
def update_weight(W,X,t):
    z = predict(X,W)
    dW = delta_weight(X, z, t)
    for i in range(len(W)):
        W[i] += dW[i]

# 学習
def learn(W,pX,T, epoch=20):
    for i in range(epoch):
        for X, t in zip(pX,T):
            update_weight(W,X,t)

感想

パーセプトロンの論文が思っていた以上に訳がわからなくて驚いた。
シンプルですが非常に奥が深く、改めてNNの面白さを実感できたので、次は多層パーセプトロンとバックプロパゲーションを実装したい。

Discussion