gpt4 book ai didi

python - 基本反向传播实现不起作用

转载 作者:太空宇宙 更新时间:2023-11-03 14:55:58 25 4
gpt4 key购买 nike

我正处于理解反向传播的早期阶段,并且我尝试自己实现它。

我尝试使用的数据集是大小为 (150, 4) 的鸢尾花数据集。

我只担心反向传播而不是梯度下降,所以我只是在一个例子上尝试我的算法,看看是否可以获得看似正确的输出。

但是,我的问题是尝试获取初始权重矩阵的渐变,但我遇到了形状错误。

我希望我的网络是这样的 -4 个输入、8 个隐藏神经元和 1 个输出神经元 Neural network

我的代码如下。 错误出现在最后一行,因为 x 的大小为 (4,1),而 delta2 的大小为 (8,8),所以我无法获得点积 我只是不明白如何如果我根据其他来源正确遵循算法,我应该得到正确的 delta2 大小。

from sklearn.datasets import load_iris
from keras.utils import to_categorical
import numpy as np

# LOAD DATA
data = load_iris()
X = data.data[:-20]
y = to_categorical(data.target[:-20])
# only 20 samples because we have a small dataset
X_test = data.data[-20:]
y_test = to_categorical(data.target[-20:])

# INIT WEIGHTS - will try to add bias later on
w1 = np.random.rand(np.shape(X)[1], h_neurons)
w2 = np.random.rand(h_neurons, 3)

def sigmoid(x, deriv=False):
if deriv:
return sigmoid(x)*(1-sigmoid(x))
else:
return 1/(1+np.exp(-x))

# Feed forward
x = X[1].reshape(4,1)
z1 = w1.T.dot(x) # need to transpose weight matrix
a1 = sigmoid(z1)
z2 = w2.T.dot(a1)
y_hat = sigmoid(z2,deriv=True) # output


# BACKPROP
y_ = y[1].reshape(3,1)
delta3 = np.multiply((y_hat - y_), sigmoid(z2, deriv=True))
dJdW2 = a1.dot(delta3) ## ERROR !!!

delta2 = np.dot(delta3, w2.T) * sigmoid(z1, deriv=True)
dJdW1 = np.dot(x.T, delta2) ## ERROR !!!

我以为我正确地实现了反向传播,但显然不是,有人可以指出我哪里出错了吗?

我被困住了,我查看了各种来源,计算 dJdW(成本相对于权重的导数)的代码大致相同。

最佳答案

我认为您的代码中有几个问题。让我们一步步解决它们。首先,这是完整的代码:

from sklearn.preprocessing import StandardScaler

def sigmoid(x, deriv=False):
if deriv:
return sigmoid(x)*(1-sigmoid(x))
else:
return 1/(1+np.exp(-x))


data = load_iris()
X = data.data[:-20]
X = StandardScaler().fit_transform(X)
y = data.target[:-20]
y = y.reshape(-1,1)

w1 = np.random.rand(np.shape(X)[1], 8)
w2 = np.random.rand(8, 1)

z1 = np.dot(X, w1) #shape (130, 8)
a1 = sigmoid(z1)
z2 = np.dot(a1, w2) #shape (130,1)
y_hat = sigmoid(z2) # l2 should also use sigmoid activation
delta3 = ((y - y_hat) * sigmoid(z2, deriv=True)) #shape (130,1)
dJdW2 = a1.T.dot(delta3) #shape (8,1)
delta2 = np.dot(delta3, w2.T) * sigmoid(z1, deriv=True) #shape (130,8)
dJdW1 = np.dot(X.T, delta2) #shape (4,8)
  1. 它与您的问题并不完全相关,但我建议缩放输入数据
  2. 一开始的y形状是(130,),值得 reshape 的是(130,1),否则可能会出现一些问题。 重要:我不使用一种热编码并将 y 保留为形状 130,1,因为一种热编码需要 softmax,sigmoid 会更糟。
  3. 我认为最好使用矢量化版本,而不是为一个示例编写代码,这样应该更容易理解。并且您需要在前向传递时使用更少的转置。

因此,您输入形状为 130, 4 的 X 和形状为 4, 8 的权重 w1。结果应具有形状 130, 8。您可以这样做:

z1 = np.dot(X, w1)
a1 = sigmoid(z1)

然后从隐藏层移动到输出层,从形状 130,8 移动到形状 130,1。并且不要忘记将激活函数应用于 y_hat:

z2 = np.dot(a1, w2)
y_hat = sigmoid(z2)

现在我们可以反向传播了。您已正确计算增量:

delta3 = np.multiply((y_hat - y_), sigmoid(z2, deriv=True)) #shape (130,1)

因此,您有形状为 (130,1) 的 delta3、形状为 130,8 的 a1,并且需要获取一个值来更新 w2,因此结果应具有形状 (8,1):

dJdW2 = a1.T.dot(delta3) #shape (8,1)

以类似的方式获取更新 w1 的值:

delta2 = np.dot(delta3, w2.T) * sigmoid(z1, deriv=True) #shape (130,8)
dJdW1 = np.dot(X.T, delta2) #shape (4,8)

所以就是这样。但我想指出的是,使用这样的模型您将无法对该数据集进行良好的预测:sigmoid 的输出范围为 0 到 1,并且 iris 数据集中有 3 个类。有几种方法可以选择:仅获取属于 2 个类的数据;对每个类使用单独的 sigmoid 或对输出层使用 softmax 激活。

关于python - 基本反向传播实现不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45576790/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com