Compute the gradient of the loss with respect to the layer parameters. Notes ----- Relies on :meth:`~numpy_ml.neural_nets.utils.im2col` and :meth:`~numpy_ml.neural_nets.utils.col2im` to vectorize the gradient calculations. Parameters
(self, dLdY, retain_grads=True)
| 3478 | return Y |
| 3479 | |
| 3480 | def backward(self, dLdY, retain_grads=True): |
| 3481 | """ |
| 3482 | Compute the gradient of the loss with respect to the layer parameters. |
| 3483 | |
| 3484 | Notes |
| 3485 | ----- |
| 3486 | Relies on :meth:`~numpy_ml.neural_nets.utils.im2col` and |
| 3487 | :meth:`~numpy_ml.neural_nets.utils.col2im` to vectorize the |
| 3488 | gradient calculations. |
| 3489 | |
| 3490 | Parameters |
| 3491 | ---------- |
| 3492 | dLdY : :py:class:`ndarray <numpy.ndarray>` of shape (`n_ex, out_rows, out_cols, out_ch`) |
| 3493 | The gradient of the loss with respect to the layer output. |
| 3494 | retain_grads : bool |
| 3495 | Whether to include the intermediate parameter gradients computed |
| 3496 | during the backward pass in the final parameter update. Default is |
| 3497 | True. |
| 3498 | |
| 3499 | Returns |
| 3500 | ------- |
| 3501 | dX : :py:class:`ndarray <numpy.ndarray>` of shape (`n_ex, in_rows, in_cols, in_ch`) |
| 3502 | The gradient of the loss with respect to the layer input volume. |
| 3503 | """ # noqa: E501 |
| 3504 | assert self.trainable, "Layer is frozen" |
| 3505 | if not isinstance(dLdY, list): |
| 3506 | dLdY = [dLdY] |
| 3507 | |
| 3508 | dX = [] |
| 3509 | X, Z = self.X, self.derived_variables["Z"] |
| 3510 | |
| 3511 | for dy, x, z in zip(dLdY, X, Z): |
| 3512 | dx, dw, db = self._bwd(dy, x, z) |
| 3513 | dX.append(dx) |
| 3514 | |
| 3515 | if retain_grads: |
| 3516 | self.gradients["W"] += dw |
| 3517 | self.gradients["b"] += db |
| 3518 | |
| 3519 | return dX[0] if len(X) == 1 else dX |
| 3520 | |
| 3521 | def _bwd(self, dLdY, X, Z): |
| 3522 | """Actual computation of gradient of the loss wrt. X, W, and b""" |