实现通用反向传播

2024-10-16 20:39:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图实现一个反向传播的方法为一个完全连接层与任意激活函数。我理解算法背后的一般思想和数学,但我在理解向量化形式上有困难。。。你知道吗

我需要帮助理解元素的预期尺寸

已知尺寸:

  • 输入-self.X是大小(N,128)
  • 重量-自身。W为尺寸(128,10)
  • 偏差-自身。b是尺寸(128,10)
  • 输出-self.y是大小(N,10)
  • 线性输出(激活前)-self.z是大小(N,10)

未知大小: 对于N=1(示例数)

  • dy-下一层的梯度-应该是多大?你知道吗
  • dz——激活函数的导数——应该是多大?你知道吗
  • self.d-当前层的梯度-应该是多大?你知道吗

这是我的密码:

def backward(self, dy):
    if self.activator == 'relu':
        dz = np.zeros((self.z.shape[0], self.z.shape[1]))
        dz[self.z>0] = 1
    elif self.activator == 'sigmoid':
        dz = self.z * (1 - self.z)
    elif self.activator == 'soft-max':
        s = self.z.reshape(-1, 1)
        dz = np.diagflat(s) - np.dot(s, s.T)
    elif self.activator == 'none':
        dz = 1

    self.d = np.dot((dz * dy), self.W.T) # the error of the layer
    self.W_grad = np.dot(self.X.T, dy) # The weight gradient of the layer
    self.b_grad = np.sum(dy, axis=0).reshape(1, -1) # The bias gradient of the layer

Tags: ofthe函数selflayer尺寸npdot
2条回答

我相信,您的代码中有一点混淆:您编写的self.z激活前的线性输出,但出于某种原因,您可以使用它来计算称为dz的激活导数。它应该使用激活值。然后,假设您计算了该值(我称之为prime,以避免与我的另一个dz混合),请尝试以下操作:

dz = dy * prime
dW = np.dot(dz, self.z.T)
db = np.sum(dz, axis=1, keepdims=True)
d = np.dot(self.W.T, dz)

几个错误:

  • self.b应该有大小self.b is size (10, )而不是(128, 10)(因为偏差是每单位的,而不是每单位对的)。你知道吗
  • self.W_grad应该是np.dot(self.X.T, (dz * dy)),而不是np.dot(self.X.T, dy)。与self.b_grad相同-应该是np.sum(dz * dy, axis=0)

其他的呢

dy := dL/dy应该是(N, 10),因为它包含y中每个元素的损失梯度

对于元素激活函数,dz := df(z)/d(z)应该是(N, 10),因为dz[i]包含df(z[i])/dz[i]。你知道吗

self.d := dL/dX应该是(N, 128),因为它包含X中每个元素的损失梯度

相关问题 更多 >