# 分解版classLeakyRelu:# 初始化def__init__(self,slope0.1):# α是一个在训练时从一个均匀分布中随机选择的参数用于控制负数区域的斜率self.slopeslope self.maskNonedefforward(self,x):self.mask(x0)yx.copy()# 复制输入数据避免修改原数据y[self.mask]self.slope*x[self.mask]returnydefbackward(self,dy):dxdy.copy()# 将x0的值都赋为slope * x[self.mask]dx[self.mask]self.slope*dx[self.mask]returndx# np版classLeakyRelu:# 初始化def__init__(self,slope0.1):# α是一个在训练时从一个均匀分布中随机选择的参数用于控制负数区域的斜率self.slopeslope self.maskNonedefforward(self,x):self.mask(x0)# 使用np.where更高效避免复制整个数组后再修改returnnp.where(self.mask,self.slope*x,x)defbackward(self,dy):# 使用np.where更高效LeakyReLU的导数是正数区域为1负数区域为slopereturnnp.where(self.mask,self.slope*dy,dy)链式法则假设网络结构是x → LeakyReLU → y → Loss前向传播x -2 y LeakyReLU(-2) slope * (-2) -0.2 Loss (y - 1)² 1.44反向传播要求什么我们要计算∂Loss/∂x也就是当 x 变化一点点时Loss 会变化多少。链式法则的应用∂Loss/∂x ∂Loss/∂y × ∂y/∂x ↑ ↑ 上游梯度 当前层的局部梯度具体计算上游传来的梯度从 Loss 传来∂Loss/∂y 2(y - 1) 2(-0.2 - 1) -2.4LeakyReLU 的局部梯度导数∂y/∂x slope 0.1 (因为 x 0)最终得到∂Loss/∂x (-2.4) × 0.1 -0.24代码对应关系defbackward(self,dy):# dy 就是上游传来的 ∂Loss/∂y -2.4dxdy.copy()# 先复制上游梯度dx[self.mask]self.slope*dx[self.mask]# 乘以局部梯度returndx# 返回 ∂Loss/∂x所以dx返回值才是真正的导数∂Loss/∂xdy输入只是上游传过来的梯度两者不是同一个东西。