eriklindernoren/ML-From-Scratch · error · NotImplementedError

NotImplementedError()

Error message

NotImplementedError()

What it means

This error is raised by the base Layer class's forward_pass method in mlfromscratch. It is an abstract-method stub: Layer is designed to be subclassed, and every concrete layer (Dense, Activation, etc.) must override forward_pass. Calling it on the base class (or on a custom layer that forgot to implement it) means no forward computation exists for that layer.

Source

Thrown at mlfromscratch/deep_learning/layers.py:27

class Layer(object):

    def set_input_shape(self, shape):
        """ Sets the shape that the layer expects of the input in the forward
        pass method """
        self.input_shape = shape

    def layer_name(self):
        """ The name of the layer. Used in model summary. """
        return self.__class__.__name__

    def parameters(self):
        """ The number of trainable parameters used by the layer """
        return 0

    def forward_pass(self, X, training):
        """ Propogates the signal forward in the network """
        raise NotImplementedError()

    def backward_pass(self, accum_grad):
        """ Propogates the accumulated gradient backwards in the network.
        If the has trainable weights then these weights are also tuned in this method.
        As input (accum_grad) it receives the gradient with respect to the output of the layer and
        returns the gradient with respect to the output of the previous layer. """
        raise NotImplementedError()

    def output_shape(self):
        """ The shape of the output produced by forward_pass """
        raise NotImplementedError()


class Dense(Layer):
    """A fully-connected NN layer.
    Parameters:
    -----------
    n_units: int

View on GitHub (pinned to a2806c6732)

Solutions

  1. Implement forward_pass(self, X, training) in your custom Layer subclass returning the layer's output for input X
  2. If you wanted a pass-through layer, subclass Layer and make forward_pass return X unchanged
  3. Don't instantiate the abstract Layer directly; use a concrete layer such as Dense
  4. Check for typos in the method name (forward_pass, not forward) so the override actually replaces the stub

Example fix

// before
class MyLayer(Layer):
    def forward(self, X):   # wrong name -> base stub raises
        return X

// after
class MyLayer(Layer):
    def forward_pass(self, X, training=True):
        return X  # custom forward computation

    def backward_pass(self, accum_grad):
        return accum_grad

    def output_shape(self):
        return self.input_shape
Defensive patterns

Strategy: type-guard

Validate before calling

def layer_is_complete(layer):
    return all(callable(getattr(layer, m, None)) and not _is_base_stub(layer, m)
               for m in ('forward_pass', 'backward_pass', 'output_shape'))

def _is_base_stub(layer, method):
    # the stubs only exist on the base Layer class
    import mlfromscratch.deep_learning.layers as L
    return getattr(type(layer), method, None) is getattr(L.Layer, method, None)

for layer in model.layers:
    assert layer_is_complete(layer), f'{type(layer).__name__} is missing required Layer methods'

Type guard

from mlfromscratch.deep_learning.layers import Layer

def is_fully_implemented_layer(obj) -> bool:
    if not isinstance(obj, Layer):
        return False
    for m in ('forward_pass', 'backward_pass', 'output_shape'):
        fn = getattr(type(obj), m, None)
        if fn is None or fn is getattr(Layer, m, None):
            return False
    return True

Prevention

When it happens

Trigger: Instantiating mlfromscratch.deep_learning.layers.Layer directly and passing it to a NeuralNetwork, or writing a custom layer subclass that does not define forward_pass(X, training) and running model.fit/predict, which invokes layer.forward_pass during the network's forward propagation.

Common situations: Developers creating custom layers who copy a subset of the API (e.g. implement only backward_pass), using the base Layer as a placeholder/no-op layer, or upgrading versions where the method signature changed to require the extra 'training' argument so an old override with a different name/signature no longer overrides it.

Related errors


AI-assisted analysis of eriklindernoren/ML-From-Scratch@a2806c6732 (2026-08-27). Data as JSON: /api/errors/f72e3d6547c4426b. Report an issue: GitHub.