反向传播实现未与XOR数据集融合

时间:2018-03-03 08:07:19

标签: python machine-learning neural-network artificial-intelligence backpropagation

我已经看过每一个地方,站了几个晚上,看了很多不同的反向传播实现(堆栈溢出)以解决这个问题,但我似乎无法理解它们是如何工作的。< / 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)

这是我得到的输出: My output

我也不了解以下内容:

  1. 在课程中,delta3仅通过以下方式计算:a3 - 目标,但是我已经看到delta3被计算的其他地方(a3 - 目标)* sigmoid(a3,derv = True)。我很困惑,哪一个是对的?为什么?
  2. 在许多实现中,该人没有使用learning_rate和(1 / m)来降低毕业。 learning_rate和(1 / m)是可选的吗?
  3. 我们应该对这些偏见做什么?更新他们?不更新它们?在许多其他实现中,我也看到人们也只是更新了偏见。
  4. 是否存在偏差所在的固定位置?像第一列或最后一列一样。等
  5. 我是否需要执行np.insert()将偏置列添加到计算中?
  6. 我非常迷失于此,所以提前谢谢你。我认为我理解反向传播,但实施它一直是一个绝对的噩梦。

1 个答案:

答案 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