![](/img/trans.png)
[英]Tensorflow implementation of Andrew Ng's cat vs non cat example (coursera)
[英]Bug in my Neural Network implementation? From Andrew Ng's class
我正在學習 Andrew Ng 的深度學習介紹 class ,我正在嘗試為原型網絡實現 python class。 網絡輸入是 (64,64,3) 的圖像,展平為 (12288,1),具有任意數量的隱藏層,以及具有 1 個節點和 sigmoid 激活 function 的 output 層。 我想我理解了求解權重和梯度的結構和方程,但即使從頭開始重新實現,網絡也只能預測每個輸入的 0,output 概率在相似范圍內,即 [[0.36001726 0.30796208 0.30430954 0.3458 , ...]]。
網絡結構如下:
使用self.init_params()
初始化網絡,它為每一層生成一個隨機權重矩陣,以及一個與層大小匹配的 np.zeros 偏置向量。
調用 model.fit(x, y) 然后:
使用self.forward()
進行前向傳遞,計算除具有 sigmoid 的最后一層之外的所有層的線性傳遞和 relu。
使用self.compute_cost()
計算此通行證的成本
使用self.backward()
計算梯度。 我認為大部分復雜性都在這里,並且可能存在錯誤。
用學習率乘以剛剛計算的梯度來更新參數。
調用model.predict(x_test)
,它使用 x_test 進行前向傳遞,並使用最后一層的 sigmoid output 來計算概率。 這些都匹配並且總是 <.5,這意味着預測為零。
訓練/測試數據沒有問題,因為簡單的 scikit-learn 邏輯回歸正在做出合理的預測。 你能幫我找出錯誤嗎?
class nn:
def __init__(self, layers, lr=.005):
self.layers = layers
self.n_layers = len(layers)-1
self.lr = lr
self.grads = {}
self.params = self.init_params()
def init_params(self):
params = {}
L = self.layers
for l in range(1, len(L)):
params[f'w{l}'] = np.random.rand(L[l], L[l-1]) * 0.01
params[f'b{l}'] = np.zeros((L[l], 1))
return params
def relu(self, z):
return np.maximum(z, 0)
def sigmoid(self, z):
return 1 / (1+np.exp(-z))
def forward(self, x):
a = x
L = self.layers
n_layers = self.n_layers
par = self.params
for l in range(1, n_layers):
z = np.dot(self.params[f'w{l}'], a) + self.params[f'b{l}']
a = self.relu(z)
self.params[f'z{l}'] = z
self.params[f'a{l}'] = a
z = np.dot(self.params[f'w{n_layers}'], self.params[f'a{n_layers-1}']) + self.params[f'b{n_layers}']
a = self.sigmoid(z)
self.params[f'z{n_layers}'] = z
self.params[f'a{n_layers}'] = a
def compute_score(self):
# cross entropy loss
m = self.m
y = self.y
y_hat = self.params[f'a{self.n_layers}']
cost = (-1/m) * (np.dot(y, np.log(y_hat).T) + np.dot((1-y), np.log(1-y_hat).T))
def back_sigmoid(self, da, z):
s = 1/(1+np.exp(-z))
dz = da * s * (1-s)
return dz
def back_relu(self, da, z):
dz = np.array(da, copy=True)
dz[z <= 0] = 0
return dz
def back_linear(self, dz, a_prev, w):
m = self.m
dw = (1/m) * np.dot(dz, a_prev.T)
db = (1/m) * np.sum(dz, axis=1, keepdims=True)
da_prev = np.dot(w.T, dz)
return dw, db, da_prev
def backward(self):
# compute daL
m = len(self.y)
nl = self.n_layers
last_a = self.params[f'a{nl}']
dal = -(np.divide(self.y, last_a) - np.divide(1-self.y, 1-last_a))
self.grads[f'da{nl}'] = dal
# first backward step (sigmoid)
dzl = self.back_sigmoid(dal, self.params[f'z{nl}'])
self.grads[f'dz{nl}'] = dzl
a_prev = self.params[f'a{nl-1}']
dw, db, da_prev = self.back_linear(dzl, a_prev, self.params[f'w{nl}'])
self.grads[f'dw{nl}'] = dw
self.grads[f'db{nl}'] = db
self.grads[f'da{nl-1}'] = da_prev
# rest of backward steps (relu)
for l in reversed(range(1, nl)):
da = self.grads[f'da{l}']
dzl = self.back_relu(da, self.params[f'z{l}'])
self.grads[f'dz{l}'] = dzl
a_prev = self.params[f'a{l-1}']
dw, db, da_prev = self.back_linear(dzl, a_prev, self.params[f'w{l}'])
self.grads[f'dw{l}'] = dw
self.grads[f'db{l}'] = db
self.grads[f'da{l-1}'] = da_prev
def fit(self, x, y, n_cycles=100):
self.params['a0'] = x
self.y = y
self.m = y.shape[1]
for i in range(n_cycles):
self.forward(x)
self.compute_score()
self.backward()
self.update_params()
def update_params(self):
for l in range(1, len(self.layers)):
self.params[f'w{l}'] = self.params[f'w{l}'] - self.lr*self.grads[f'dw{l}']
self.params[f'b{l}'] = self.params[f'b{l}'] - self.lr*self.grads[f'db{l}']
def predict(self, x):
self.forward(x)
yhat = self.params[f'a{self.n_layers}']
print(yhat)
return 1. * (yhat >= .5)
layers = [12288, 5, 3, 1]
network = nn(layers)
network.fit(x_train, y_train, n_cycles=100)
network.predict(x_test) # gives all 0s
在我的本地機器上運行代碼時,有兩條錯誤消息。 第一個是關於 numpy 導入,可以通過將 numpy 作為 np 導入(將 numpy 作為 np 導入)來刪除。 另一個錯誤是由於 x_train,y_train 未在全局空間上定義而出現的。 看起來它直接用於調用 network.fit() function 沒有事先聲明和定義。 但是由於您上面的問題表明您已經運行程序沒有錯誤,唯一可能的問題可能是 model 沒有針對設定的時期數進行訓練。 看起來培訓只進行了一次
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.