剖析正向传播&反向传播_两层神经网络(二)

一般性理论+反向求导程序实现(二分类均方差损失函数、二分类交叉熵损失函数)。(欢迎指正)

1.两层神经网络

1.1网络结构

在这里插入图片描述

1.2正向传播

在这里插入图片描述

1.3规律

在这里插入图片描述

1.4正向传播公式

在这里插入图片描述

1.5单样本_反向传播公式

在这里插入图片描述

1.6反向传播

在这里插入图片描述

1.7.m个样本_反向传播_代码实现

在这里插入图片描述

2.实例(二分类均方差损失函数):

2.1前提

  • 两层神经网络;
  • 第一层激活函数:tanh
  • 第二层激活函数:sigmoid
  • 损失函数:均方差损失函数

2.2前向传播

在这里插入图片描述

2.3反向求导

在这里插入图片描述

2.4代码实现

#前向传播较为简单,这里就略掉。
#以下为反向求导:
class MSELoss(Module):

    def __call__(self, output, target):
        assert(target.ndim == 2)
        self.A = output
        self.Y = target
        self.m = target.shape[0]
        return self.forward(self.A, self.Y)

    def forward(self, A, Y):
        self.loss = np.sum(np.square(A - Y)) / self.m
        return self

    def float(self):
        return self.loss

    def backward(self):
        #第二层
        dA2 = 2 * (self.A - self.Y)/self.m
        dZ2 = dA2 * (self.A * (1 - self.A))
        x_input = self.get_cache_input()
        A1 = next(x_input)
        dW2 = np.dot(dZ2.T, A1) / self.m 
        dB2 = np.sum(dZ2.T, axis=1,keepdims=True) #

        # 第一层
        params = self.parameters()
        W2 = next(params).weight
        dA1 = np.dot(dZ2, W2)
        dZ1 = dA1 * (1 - np.square(A1))
        X1 = next(x_input)
        dW1 = np.dot(dZ1.T, X1) / self.m
        dB1 = np.sum(dZ1.T, axis=1, keepdims=True)
        return {"dW2":dW2, "dB2":dB2, "dW1":dW1, "dB1":dB1}

3.实例(二分类交叉熵损失函数)

3.1前提

  • 两层神经网络;
  • 第一层激活函数:tanh
  • 第二层激活函数:sigmoid
  • 损失函数:二分类交叉熵差损失函数

3.2前向传播

在这里插入图片描述

3.3反向求导

在这里插入图片描述

3.4代码实现

#前向传播较为简单,这里就略掉。
#以下为反向求导:
class BCELoss(Module):
    def __call__(self, output, target):
        self.A = output
        self.Y = target
        self.m = target.shape[0]
        return self.forward(self.A, self.Y)

    def forward(self, A, Y):
        self.loss = -np.sum(Y*np.log(A) + (1 - Y) * np.log(1 - A))/ self.m
        return self

    def float(self):
        return self.loss

    def backward(self):
        dA2 = (1 - self.Y) / (1 - self.A) - self.Y / self.A
        dZ2 = dA2 * (self.A * (1 - self.A))
        x_input = self.get_cache_input()
        A1 = next(x_input)
        dW2 = np.dot(dZ2.T, A1) / self.m  # 一批样本的平均导数
        dB2 = np.sum(dZ2.T, axis=1, keepdims=True)  #

        # 往前求第一层的导数
        params = self.parameters()
        W2 = next(params).weight
        dA1 = np.dot(dZ2, W2)
        # 用的是tanh激活
        dZ1 = dA1 * (1 - np.square(A1))
        X1 = next(x_input)

        dW1 = np.dot(dZ1.T, X1) / self.m
        dB1 = np.sum(dZ1.T, axis=1, keepdims=True)
        return {"dW2": dW2, "dB2": dB2, "dW1": dW1, "dB1": dB1}
发布了29 篇原创文章 · 获赞 45 · 访问量 5052

猜你喜欢

转载自blog.csdn.net/sinat_39783664/article/details/103161562