神经网络反向传播代码不工作

我需要编写一个简单的由1个输出节点、1个包含3个节点的隐藏层和1个输入层(大小可变)组成的神经网络。现在我只是尝试用xor数据进行训练,所以我们假设有3个输入节点(其中一个节点代表偏置,始终为1)。数据标记为0,1。

我推导了反向传播的方程,发现尽管非常简单,我的代码并未能使xor数据收敛到正确的结果。

设W为连接输入层和隐藏层的3×3权重矩阵,w为连接隐藏层和输出层的1×3矩阵。以下是我方法的一些辅助函数

def feed_forward_predict(x, W, w):    sigmoid = lambda x: 1/(1+np.exp(-x))    z = np.array(list(map(sigmoid, np.matmul(W, x))))    L = sigmoid(np.matmul(w, z))    return [L, z, x]

这个函数只是接收一个值并使用公式sig(w*sig(W*x))进行预测。我们还有

def calculate_objective(data, labels, W, w):    obj = 0    for point, label in zip(data, labels):        L, z, x = feed_forward_predict(point, W, w)        obj += (label - L)**2        return obj

这个函数计算一组给定数据点的均方误差。这两个函数应该都能正常工作,因为我手动检查过它们。现在问题出现在反向传播算法中

def back_prop(traindata, trainlabels):    sigmoid = lambda x: 1/(1+np.exp(-x))    sigmoid_prime = lambda x: np.exp(-x)/((1+np.exp(-x))**2)    W = np.random.rand(3, len(traindata[0]))    w = np.random.rand(1, 3)    obj = calculate_objective(traindata, trainlabels, W, w)    print(obj)    epochs = 10_000    eta = .01    prevobj = np.inf    i=0    while(i < epochs):        prevobj = obj        dellw = np.zeros((1,3))        for point, label in zip(traindata, trainlabels):            y, z, x = feed_forward_predict(point, W, w)            dellw += 2*(y - label) * sigmoid_prime(np.dot(w, z)) * z        w -= eta * dellw             for point, label in zip(traindata, trainlabels):            y, z, x = feed_forward_predict(point, W, w)            temp = 2 * (y - label) * sigmoid_prime(np.dot(w, z))            # 注意s,u,v代表隐藏节点的权重。我的教授要求这样做            dells = temp * w[0][0] * sigmoid_prime(np.matmul(W[0,:], x)) * x                       dellu = temp * w[0][1] * sigmoid_prime(np.matmul(W[1,:], x)) * x                        dellv = temp * w[0][2] * sigmoid_prime(np.matmul(W[2,:], x)) * x        dellW = np.array([dells, dellu, dellv])        W -= eta*dellW        obj = calculate_objective(traindata, trainlabels, W, w)        i = i + 1        print("i=", i, " Objective=",obj)    return [W, w]

然而,尽管在矩阵乘法和导数计算上看似正确,这段代码并未能收敛到任何结果。实际上,误差一直在波动:先下降,然后上升,再次下降到相同的位置,然后再次上升。我认为问题出在W矩阵的梯度上,但我不知道具体是什么问题。

如果你想亲眼看看发生了什么,我使用的输入数据是

0: 0 0 10: 1 1 11: 1 0 11: 0 1 1

其中第一个数字代表标签。我还将随机种子设置为np.random.seed(0),这样我处理的矩阵就能保持一致。


回答:

我想我已经解决了问题,在我的代码中,我没有对隐藏节点权重的导数进行累加,而是在每次循环迭代时进行了赋值。正确的版本应该是这样的

for point, label in zip(traindata, trainlabels):      y, z, x = feed_forward_predict(point, W, w)      temp = 2 * (y - label) * sigmoid_prime(np.dot(w, z))      # 注意s,u,v代表隐藏节点的权重。我的教授要求这样做      dells += temp * w[0][0] * sigmoid_prime(np.matmul(W[0,:], x)) * x                 dellu += temp * w[0][1] * sigmoid_prime(np.matmul(W[1,:], x)) * x                  dellv += temp * w[0][2] * sigmoid_prime(np.matmul(W[2,:], x)) * x

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注