在这里,我试图实现一个带有单个隐藏层的神经网络来对两个训练示例进行分类。该网络利用 sigmoid 激活函数。
层的尺寸和权重如下:
X : 2X4
w1 : 2X3
l1 : 4X3
w2 : 2X4
Y : 2X3
我在反向传播中遇到了矩阵维度不正确的问题。此代码:
import numpy as np
M = 2
learning_rate = 0.0001
X_train = np.asarray([[1,1,1,1] , [0,0,0,0]])
Y_train = np.asarray([[1,1,1] , [0,0,0]])
X_trainT = X_train.T
Y_trainT = Y_train.T
A2_sig = 0;
A1_sig = 0;
def sigmoid(z):
s = 1 / (1 + np.exp(-z))
return s
def forwardProp() :
global A2_sig, A1_sig;
w1=np.random.uniform(low=-1, high=1, size=(2, 2))
b1=np.random.uniform(low=1, high=1, size=(2, 1))
w1 = np.concatenate((w1 , b1) , axis=1)
A1_dot = np.dot(X_trainT , w1)
A1_sig = sigmoid(A1_dot).T
w2=np.random.uniform(low=-1, high=1, size=(4, 1))
b2=np.random.uniform(low=1, high=1, size=(4, 1))
w2 = np.concatenate((w2 , b2) , axis=1)
A2_dot = np.dot(A1_sig, w2)
A2_sig = sigmoid(A2_dot)
def backProp() :
global A2_sig;
global A1_sig;
error1 = np.dot((A2_sig - Y_trainT).T, A1_sig / M)
print(A1_sig)
print(error1)
error2 = A1_sig.T - error1
forwardProp()
backProp()
返回错误:
ValueError Traceback (most recent call last)
<ipython-input-605-5aa61e60051c> in <module>()
45
46 forwardProp()
---> 47 backProp()
48
49 # dw2 = np.dot((Y_trainT - A2_sig))
<ipython-input-605-5aa61e60051c> in backProp()
42 print(A1_sig)
43 print(error1)
---> 44 error2 = A1_sig.T - error1
45
46 forwardProp()
ValueError: operands could not be broadcast together with shapes (4,3) (2,4)
如何计算前一层的误差?
更新 :
import numpy as np
M = 2
learning_rate = 0.0001
X_train = np.asarray([[1,1,1,1] , [0,0,0,0]])
Y_train = np.asarray([[1,1,1] , [0,0,0]])
X_trainT = X_train.T
Y_trainT = Y_train.T
A2_sig = 0;
A1_sig = 0;
def sigmoid(z):
s = 1 / (1 + np.exp(-z))
return s
A1_sig = 0;
A2_sig = 0;
def forwardProp() :
global A2_sig, A1_sig;
w1=np.random.uniform(low=-1, high=1, size=(4, 2))
b1=np.random.uniform(low=1, high=1, size=(2, 1))
A1_dot = np.dot(X_train , w1) + b1
A1_sig = sigmoid(A1_dot).T
w2=np.random.uniform(low=-1, high=1, size=(2, 3))
b2=np.random.uniform(low=1, high=1, size=(2, 1))
A2_dot = np.dot(A1_dot , w2) + b2
A2_sig = sigmoid(A2_dot)
return(A2_sig)
def backProp() :
global A2_sig;
global A1_sig;
error1 = np.dot((A2_sig - Y_trainT.T).T , A1_sig / M)
error2 = error1 - A1_sig
return(error1)
print(forwardProp())
print(backProp())
返回错误:
ValueError Traceback (most recent call last)
<ipython-input-664-25e99255981f> in <module>()
47
48 print(forwardProp())
---> 49 print(backProp())
<ipython-input-664-25e99255981f> in backProp()
42
43 error1 = np.dot((A2_sig - Y_trainT.T).T , A1_sig / M)
---> 44 error2 = error1.T - A1_sig
45
46 return(error1)
ValueError: operands could not be broadcast together with shapes (2,3) (2,2)
是否错误地设置了矩阵维度?
最佳答案
你的第一个权重矩阵,w1
, 应该是形状 (n_features, layer_1_size)
,所以当你乘以一个输入时,X
形状(m_examples, n_features)
来自 w1
,你会得到一个 (m_examples, layer_1_size)
矩阵。这通过第 1 层的激活运行,然后馈入第 2 层,该层应具有形状为 (layer_1_size, output_size)
的权重矩阵,其中 output_size=3
因为您正在对 3 个类别进行多标签分类。如您所见,重点是将每一层的输入转换为适合该层中神经元数量的形状,或者换句话说,层的每个输入都必须馈入该层中的每个神经元。
我不会像你那样对你的层输入进行转置,我会按照描述的那样塑造权重矩阵,这样你就可以计算 np.dot(X, w1)
, 等等。
看起来您也没有正确处理偏见。当我们计算 Z = np.dot(w1,X) + b1
, b1
应该广播,以便将其添加到 w1
的产品的每一列中。和 X
.如果您附加 b1
,则不会发生这种情况。到您拥有的权重矩阵。相反,您应该添加一列 ones
到您的输入矩阵和权重矩阵的附加行,因此偏差项位于权重矩阵的该行和 ones
在您的输入中确保它们被添加到任何地方。在此设置中,您不需要单独的 b1
, b2
条款。
X_train = np.c_(X_train, np.ones(m_examples))
记得在你的权重上再增加一行,所以
w1
应该有形状 (n_features+1, layer_1_size)
.反向传播更新:
反向传播的目标是计算误差函数相对于权重和偏差的梯度,并使用每个结果来更新每个权重矩阵和每个偏差向量。
所以你需要
dE/dw2
, dE/db2
, dE/dw1
, 和 dE/db1
所以你可以应用更新:w2 <- w2 - learning_rate * dE/dw2
b2 <- b2 - learning_rate * dE/db2
w1 <- w1 - learning_rate * dE/dw1
b1 <- b1 - learning_rate * dE/db1
由于您正在进行多标签分类,因此您应该使用二元交叉熵损失:
您可以计算
dE/dw2
使用链式法则:dE/dw2 = (dE/dA2) * (dA/dZ2) * (dZ2/dw2)
我正在使用
Z
为您 A2_dot
由于尚未应用激活,我正在使用 A2
为您 A2_sig
.见 Notes on Backpropagation [pdf]有关使用 sigmoid 激活的交叉熵损失的详细推导。然而,这提供了逐点推导,而我们正在寻找矢量化实现,因此您将不得不做一些工作来找出矩阵的正确布局。不幸的是,也没有明确的偏差向量。
您对
error1
的表达式看起来正确,但我会称它为 dw2
,我只会使用 Y_train
而不是进行两次转置:dw2 = (1/m) * np.dot((A2 - Y_train).T , A1)
你还需要
db2
应该是:db2 = (1/m) * np.sum(A2 - Y_train, axis=1, keepdims=True)
您必须进一步应用链式法则才能获得
dw1
和 db1
,我会把它留给你,但在 Neural Networks and Deep Learning 的第 3 周有一个很好的推导Coursera 类(class)。除了我认为您不应该在反向传播代码中进行该计算之外,我不能说太多关于您遇到错误的行,因此尺寸不匹配是有道理的。您可能会想到输出端的梯度,但我想不出任何涉及
A1
的类似表达式。用于此网络中的反向传播。This article在 numpy 中有一个非常好的单隐藏层神经网络实现。它确实在输出端使用了 softmax,但它在隐藏层中有 sigmoid 激活,否则计算上的差异很小。它应该可以帮助您计算
dw1
和 db1
为隐藏层。具体看 delta1
的表达式在标题为“实践中的神经网络”的部分中。将他们的计算转换为我们使用的符号,并在输出中使用 sigmoid 而不是 softmax,它应该如下所示:
dZ2 = A2 - Y_train
dZ1 = np.dot(dZ2, w2.T) * A1 * (1 - A1) # element-wise product
dw2 = (1/m) * np.dot(dZ2, A1.T)
db2 = (1/m) * np.sum(dZ2, axis=1, keepdims=True)
dw1 = (1/m) * np.dot(dZ1, X_train.T)
db1 = (1/m) * np.sum(dZ1, axis=1, keepdims=True)
关于python - 矩阵维度在反向传播中不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47844093/