我已经看过每一个地方,站了几个晚上,看了很多不同的反向传播实现(堆栈溢出)以解决这个问题,但我似乎无法理解它们是如何工作的。< / p>
我目前正在参加Andrew Ng的课程机器学习课程并且它非常棒,但该课程中显示的后方实施与我在互联网上看到的非常不同。
我在理解尺寸和计算每个重量的增量方面遇到了问题。我真的很感激,如果有人能给我一个关于反向传播的确切结果。我在前方道具中没有问题。
这是我的代码(跳到第一个for循环)。
import numpy as np
import sys
x_train = np.array([
[1, 0, 1],
[1, 1, 0],
[1, 1, 1],
[1, 0, 0]
])
y_train = np.array([
[1],
[1],
[0],
[0]
])
learning_rate = 0.03
reg_param = 0.5
num_h_units = 5
max_iter = 60000 # for gradient descent
m = 4 # training
np.random.seed(1)
weights1 = np.random.random((x_train.shape[1], num_h_units)) # 3x5 (Including bias)
weights2 = np.random.random((num_h_units + 1, 1)) # 6x1 (Including bias)
def sigmoid(z, derv=False):
if derv: return z * (1 - z)
return (1 / (1 + np.exp(-z)))
def forward(x, predict=False):
a1 = x # 1x3
a1.shape = (1, a1.shape[0]) # Reshaping now, to avoid reshaping the other activations.
a2 = np.insert(sigmoid(a1.dot(weights1)), 0, 1, axis=1) # 1x3 * 3x5 = 1x5 + bias = 1x6
a3 = sigmoid(a2.dot(weights2)) # 1x6 * 6x1 = 1x1
if predict: return a3
return (a1, a2, a3)
w_grad1 = 0
w_grad2 = 0
for i in range(max_iter):
for j in range(m):
sys.stdout.write("\rIteration: {} and {}".format(i + 1, j + 1))
a1, a2, a3 = forward(x_train[j])
delta3 = np.multiply((a3 - y_train[j]), sigmoid(a3, derv=True)) # 1x1
# (1x6 * 1x1) .* 1x6 = 1x6 (Here, ".*" stands for element wise mult)
delta2 = np.multiply((weights2.T * delta3), sigmoid(a2, derv=True))
delta2 = delta2[:, 1:] # Getting rid of the bias value since that shouldn't be updated.
# 3x1 * 1x5 = 3x5 (Gradient of all the weight values for weights connecting input to hidden)
w_grad1 += (1 / m) * a1.T.dot(delta2)
# 6x1 * 1x1 = 6x1 (Updating the bias as well. If bias is removed, dimensions don't match)
a2[:, 0] = 0
w_grad2 += (1 / m) * a2.T.dot(delta3)
sys.stdout.flush() # Updating the text.
weights1 -= learning_rate * w_grad1
weights2 -= learning_rate * w_grad2
# Outputting all the outputs at once.
a1_full = x_train
a2_full = np.insert(sigmoid(a1_full.dot(weights1)), 0, 1, axis=1)
a3_full = sigmoid(a2_full.dot(weights2))
print(a3_full)
我也不了解以下内容:
我非常迷失于此,所以提前谢谢你。我认为我理解反向传播,但实施它一直是一个绝对的噩梦。
答案 0 :(得分:1)
https://nodejs.org/en/download/是我所知道的最好直观的反推法解释。强烈推荐。
1.你使用什么损失功能?如果你使用交叉熵损失(登录它的那个)那么delta3必须只是(a3 - 目标)。对于最小二乘损失,另一个是正确的。仅使用(a3 - y_train [j])in你的代码。
2.学习率和1 / m不是可选的。
3.应该始终更新偏见。
4.尝试分开初始化偏见和权重。我发现它更容易理解。
前向传球示例:
Z1 =权重* X +偏差
A1 = sigmoid(Z1)
请参阅This。我使用numpy实现了完全相同的功能,但它确实有效。
更正:
delta3 = a3 - y_train [j]
delta2 = np.multiply((weights2.T * delta3),sigmoid_prime(z1))
,其中 sigmoid_prime是:
def sigmoid_prime(z):
return sigmoid(z)*(1-sigmoid(z))
和z1是a1.dot(weights1)
。您的前馈功能也需要返回此值,以便您可以在此处使用。
此外,由于你使用的是随机梯度下降(而不是小批量梯度下降),你的m实际上是1。所以你应该删除1 / m项。
使用np.random.normal而不是np.random.random
初始化权重不要摆脱偏见条款。
阅读上面链接的back-prop以及this notebook