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()
![]() |
單位步級函數 |
$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()
![]() |
線性可分離 |
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 分類 |
$\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運算。需注意的是並非所有分類的問題是「線性可分離」,所以演算法中需定義一個最大的訓期限制的超參數,當到此限制時訓練尚未完成則程式必需停止。
沒有留言:
張貼留言