講師:溫室蔡
機器學習[2]
隱藏層
輸入層
輸出層
權重
權重
代入
代入
雖然經過了多層的變換
最後一層與第一層卻依然是線性關係
依然是線性分類器
在前向傳播中加入一些非線性的函數
輸入
輸出
正解
差異
我們沒辦法直接求得損失函數的最小值
但我們可以從函數圖形的角度去思考
求出「目前參數下,損失函數圖形的梯度」
然後將參數往梯度反方向更新
就可以在損失函數圖形上往下坡走
損失
參數
損失
參數
損失
參數
損失
參數
梯度下降可以用以下的數學式描述:
更新後參數
目前參數
學習率
(下降步長)
損失函數梯度
函數圖形在某點的斜率
函數圖形在某點的斜率
函數圖形在某點的斜率
計算微分的一種方法
是直接從微分的定義做起
註:
是
的簡便寫法
所以實務上是直接記住微分的規則
直接從定義做會很麻煩
然後照這些規則去計算
次方律:
加法律:
乘法律:
連鎖律:
微分
微分
微分
微分
輸入
輸出
正解
差異
輸出
正解
差異
因此我們可得:
若要更新更前面一層的權重,我們會計算
若要更新更前面一層的權重,我們會計算
如何求得?
在計算上一層梯度的時候
就可以先計算
以此類推,這就是「反向傳播」的概念
層計算出 給 層使用
層再計算出 給 層使用
import numpy as np
class NeuralNetwork:
def __init__(self, layer_sizes, act, dact):
self.layer_sizes = layer_sizes
self.num_layers = len(layer_sizes) - 1
self.act = act
self.dact = dact
self.weights = []
self.biases = []
self.zetas = []
self.values = []
for i in range(self.num_layers):
self.weights.append(np.random.randn(layer_sizes[i+1], layer_sizes[i]))
self.biases.append(np.random.randn(layer_sizes[i+1], 1))
self.zetas.append(np.zeros((layer_sizes[i+1], 1)))
self.values.append(np.zeros((layer_sizes[i], 1)))
self.values.append(np.zeros((layer_sizes[-1], 1)))
def forward(self, data):
self.values[0] = data
for i in range(self.num_layers):
self.zetas[i] = np.dot(self.weights[i], self.values[i]) + self.biases[i]
self.values[i+1] = self.act(self.zetas[i])
def backward(self, label, lr):
dx = self.values[-1] - label
for i in range(self.num_layers):
j = self.num_layers - i - 1
db = dx * self.dact(self.zetas[j])
dW = np.dot(db, self.values[j].T)
dx = np.dot(self.weights[j].T, db)
self.weights[j] -= lr * dW
self.biases[j] -= lr * db
def predict(self, data):
self.forward(data)
return self.values[-1]
def fit(self, data, labels, lr, epochs):
for i in range(epochs):
print(i)
for j in range(len(data)):
self.forward(data[j])
self.backward(labels[j], lr)
實作 XOR 閘
是最簡單的非線性問題
因為它的資料點
沒辦法被一條直線分類
from nn import NeuralNetwork
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def dsigmoid(x):
return sigmoid(x) * (1 - sigmoid(x))
if __name__ == '__main__':
data = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]).reshape((4, 2, 1))
labels = np.array([0, 1, 1, 0]).reshape((4, 1, 1))
model = NeuralNetwork([2, 4, 4, 1], sigmoid, dsigmoid)
model.fit(data, labels, 1, 1000)
for x in data:
print(model.predict(x))