2018/12/3

Perceptron (感知元)

08 Perceptron (感知元)

Perceptron (感知元)  是構成神經網路最基本的單元,含有輸入、輸出、核心計算單元三個部份,計算單元執行activate function (作動函數),依輸入決定輸出。每一輸入是實例的一個特徵,一般外加一個 bias(偏置)輸入,其值永設為1,所以若實例有$n$個特徵,則感知元就有$n+1$個輸入。每一個輸入連接至感知元的連線上有一weight(權重)係數,感知元計算輸入和權重的線性組合,依作動函數決定輸出值。一般常用的作動函數有sigmoid function 和unit step function (單位步級函數),sigmoid function之前已討論過,而單位步級函數依輸入的正負值決定輸出,若是負則輸出0,若是正則輸出1,如
import matplotlib.pyplot as plt
import numpy as np
def step_function(x):
    return 1 if x >= 0 else 0
x = np.arange(-6,6,0.01)
y = x.copy()
for i in range(len(x)):
    a = step_function(y[i] )
    y[i] = a
plt.grid(True)
plt.plot(x,y)
plt.show()
單位步級函數
若有所 $n$ 個特徵,$x_i,\,i=1\sim n$,此情況需 $n+1$ 權重係數,$w_i,\,i=0\sim n$,感知元先依輸入求得$y_{\rm{in}}$
$y_{\rm {in}}=\sum_{i=0}^{n}w_ix_i, \hspace{0.2cm} {\rm with}\hspace{0.1cm} x_0=1$
如作動函數是單位步級函數,則感知元的輸出可表示成
$\phi(y_{\rm{in}})=\left \{ \begin{array}{l}
1,\, y_{\rm{in}}>0\\
0,\, \rm{elsewhere}
\end{array} \right.
$
如作動函數是 sigmoid 函數,則感知元的輸出可表示成
$\phi(y_{\rm{in}})=\frac{1}{1+e^{-y_{\rm {\hspace{0.05cm}in}}}}$

∎ 感知元實現邏輯閘
常用的邏輯閘有AND gate (或閘), OR gate (及閘), 和 XOR gate (互斥或閘),假設有兩輸入 $a$ 和 $b$,一輸出 $y$ ,其真值表如下:

下表是 AND gate (兩輸入為1時輸出是1,否則為0
$a$ $b$ $y$
1 1 1
1 0 0
0 1 0
0 0 0

下表是 OR gate (只要有1出現輸出是1,否則為0
$a$ $b$ $y$
1 1 1
1 0 1
0 1 1
0 0 0

下表是 XOR gate (兩輸入不同則輸出是1,相同則為0
$a$ $b$ $y$
1 1 0
1 0 1
0 1 1
0 0 0

要用感知元實現邏輯閘,有一個重要的觀念是輸入的點是否為「線性可分離」,亦即是否可用一條直線依需要分離出輸入點。
x = [1,1,0,0]
y = [1,0,1,0]
plt.figure()
plt.plot(x, y, 'k.')
x1 = np.linspace(-0.5,1.5)
y1 = 0.5 - x1
plt.plot(x1, y1, 'r')
y2 = 1.5 - x1
plt.plot(x1, y2, 'b')
plt.axis([-0.5, 1.5, -0.5, 1.5])
plt.grid(True)
plt.show()

線性可分離
圖中可見藍色線可將4個點分離成兩邊而實現AND gate 的功能,線的右上邊為1,另邊為 0,相同的紅色線也可將4個點分離成兩邊而實現OR gate 的功能,線的右上邊為1,另邊為 0。但是一條直線無法實現XOR gate的功能,因而在實際的應用是用多級感知元串接,且每一級又會有多個並接,形成 Neural Network (神經網路)。 下列程式可實現 AND gate
def step_function(x):
    return 1 if x >= 0 else 0
def perceptron_output(weights, bias, x):
    calculation = np.dot(weights, x) + bias
    return step_function(calculation)
weights = [2, 2]  #AND gate
bias = -3
x=[1,1]
print(perceptron_output(weights, bias, x))
1
下列程式可實現 OR gate
def step_function(x):
    return 1 if x >= 0 else 0
def perceptron_output(weights, bias, x):
    calculation = np.dot(weights, x) + bias
    return step_function(calculation)
weights = [2, 2]  #OR  gate
bias = -1
x=[0,0]
print(perceptron_output(weights, bias, x))
0
程式中 weights 為已知,但在實際的應用上weights 需透過訓練求得,再以求得的值代入運算,對資料進行分類。

∎ 感知元學習演算法
演算法的基本運算類似梯度下降法,是以誤差來更新權重,更新的規則如下
$w_i(t+1)=w_i(t)+\alpha (d_j-y_j(t))x_{j,i}$, for all features $0\leq i \leq n$
其中$j$表示實例,而$i$是特徵,$d_j$是第$j$實例的目標值,而$y_j(t)$是時間$t$對實例$j$的輸出值,$\alpha$是learning rate  (學習率)決定每次更新量的大小,是一系統的hyperparameter (超參數),指在系統的模型中並沒有此一參數,而是學習演算法外加的參數,而係統模型有包括的如權重係就稱為parameter (參數)。一般開始時,參數 $w_i(0)$可設為0或一隨機的小數目。
以學習AND gate的分類實際演練,如下
import numpy as np
import matplotlib.pyplot as plt
X_train = np.array([
    [1, 1],
    [1, 0],
    [0, 1],
    [0, 0],   ])
y_train = [1, 1, 1, 0]
plt.figure()
plt.xlabel('feature 1')
plt.ylabel('feature 2')
for i, x in enumerate(X_train):
    plt.scatter(x[0], x[1], c='r', marker='x' if y_train[i] == 1 else 'D')
plt.grid(True)
plt.show()

AND gate 分類
如之前所提的例子,此圖的點若要以 AND gate分類是可線性分離的。首先我們可將特徵以矩陣表示成
$\boldsymbol{x}=[\begin{matrix}1 &x_1  & x_2 \end{matrix}]^T$,並把重係數表示成 $\boldsymbol{w}=[\begin{matrix}w_0 &w_0  & w_2 \end{matrix}]$,則作動函數的運算可表示成 $\phi (\boldsymbol{w}\boldsymbol{x})$。
import numpy as np
import matplotlib.pyplot as plt
def unit_step(x):
    return 1 * (x > 0)
X_train = np.array([
    [1, 1],
    [1, 0],
    [0, 1],
    [0, 0],   ])
y_train = [1, 0, 0, 0]
u=np.array([[1.0]])
change=False
W = np.array([[0.0, 0.0, 0.0]])
for i in range(0,4):
    X= X_train[i]
    X=np.reshape(X,(2,1))
    X=np.r_[u,X]
    y = unit_step(np.matmul(W,X))
    if y != y_train[i]:
        change=True
        for j in range(0,3):
            W[:,j] = W[:,j]+(y_train[i]-y)*X[j]
            print(W)
if change == False:
    print("Finished")
else:
    print("Not yet finished")
print(W)
[[1. 0. 0.]]
[[1. 1. 0.]]
[[1. 1. 1.]]
[[0. 1. 1.]]
[[0. 0. 1.]]
[[0. 0. 1.]]
[[-1.  0.  1.]]
[[-1.  0.  1.]]
[[-1.  0.  0.]]
Not yet finished
[[-1.  0.  0.]]
此例中我們有4個實例,每例有兩個及數,所以需3個權重係數,程式開始都設成0,為了要執行 $\phi (\boldsymbol{w}\boldsymbol{x})$,把$\boldsymbol{x}$表示行矩陣,程式第16行reshape(X,(2,1))就是把實例表示成$2\times 1$的行陣,第17行 r_[u,X]是在$\boldsymbol{x}$ 第 0 列插入1,使得成為$[\begin{matrix}1 &x_1  & x_2 \end{matrix}]^T$之形式,之後執行矩陣相乘並帶入unit step function,並七較輸出和目標值,如不同則依更新規則進行更新。在訓練過程中,4個實例都執行一次稱為一個epoch (訓期),當一訓期中權重係數都沒有被改變表示訓練完成,否則需以每訓期最後的係數再進行下一訓期的訓練,直至學習結束。此例中並未完成,需 再把[[-1.  0.  0.]]帶入W進行下一訓期,得第二訓期輸出為
[[0. 0. 0.]]
[[0. 1. 0.]]
[[0. 1. 1.]]
[[-1.  1.  1.]]
[[-1.  0.  1.]]
[[-1.  0.  1.]]
Not yet finished
[[-1.  0.  1.]]
依然還沒完成,再帶入[[-1.  0.  1.]],得第三訓期輸出為
[[0. 0. 1.]]
[[0. 1. 1.]]
[[0. 1. 2.]]
[[-1.  1.  2.]]
[[-1.  0.  2.]]
[[-1.  0.  2.]]
[[-2.  0.  2.]]
[[-2.  0.  2.]]
[[-2.  0.  1.]]
Not yet finished
[[-2.  0.  1.]]
依然還沒完成,再帶入[[-2.  0.  1.]],得第四訓期輸出為
[[-1.  0.  1.]]
[[-1.  1.  1.]]
[[-1.  1.  2.]]
[[-2.  1.  2.]]
[[-2.  1.  2.]]
[[-2.  1.  1.]]
Not yet finished
[[-2.  1.  1.]]
依然還沒完成,再帶入[[-2.  1.  1.]],得第五訓期輸出為
[[-1.  1.  1.]]
[[-1.  2.  1.]]
[[-1.  2.  2.]]
[[-2.  2.  2.]]
[[-2.  1.  2.]]
[[-2.  1.  2.]]
Not yet finished
[[-2.  1.  2.]]
依然還沒完成,再帶入[[-2.  1.  2.]],得第六訓期輸出為
Finished
[[-2.  1.  2.]]
經過六個訓期終於完成,則我們可以此係數執行AND gate運算。需注意的是並非所有分類的問題是「線性可分離」,所以演算法中需定義一個最大的訓期限制的超參數,當到此限制時訓練尚未完成則程式必需停止。

沒有留言:

張貼留言