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

我需要编写一个简单的由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

如何对SVC进行超参数调优?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

如何在初始训练后向模型添加训练数据?

我想在我的scikit-learn模型已经训练完成后再…

使用Google Cloud Function并行运行带有不同用户参数的相同训练作业

我正在寻找一种方法来并行运行带有不同用户参数的相同训练…

加载Keras模型,TypeError: ‘module’ object is not callable

我已经在StackOverflow上搜索并阅读了文档,…

在计算KNN填补方法中特定列中NaN值的”距离平均值”时

当我从头开始实现KNN填补方法来处理缺失数据时,我遇到…

使用巨大的S3 CSV文件或直接从预处理的关系型或NoSQL数据库获取数据的机器学习训练/测试工作

已关闭。此问题需要更多细节或更清晰的说明。目前不接受回…

发表回复

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