d2l-ai/d2l-zh · error · NotImplementedError

NotImplementedError

Error message

NotImplementedError

What it means

NotImplementedError raised by Encoder.forward in d2l.torch (the abstract encoder interface for the encoder-decoder architecture, sec_encoder-decoder). Encoder subclasses nn.Module but provides no default forward behavior; instantiating it directly and calling it (or using a subclass that fails to override forward) hits the guard. Concrete encoders like Seq2SeqEncoder supply the real forward.

Source

Thrown at d2l/torch.py:936

    text = preprocess_nmt(read_data_nmt())
    source, target = tokenize_nmt(text, num_examples)
    src_vocab = d2l.Vocab(source, min_freq=2,
                          reserved_tokens=['<pad>', '<bos>', '<eos>'])
    tgt_vocab = d2l.Vocab(target, min_freq=2,
                          reserved_tokens=['<pad>', '<bos>', '<eos>'])
    src_array, src_valid_len = build_array_nmt(source, src_vocab, num_steps)
    tgt_array, tgt_valid_len = build_array_nmt(target, tgt_vocab, num_steps)
    data_arrays = (src_array, src_valid_len, tgt_array, tgt_valid_len)
    data_iter = d2l.load_array(data_arrays, batch_size)
    return data_iter, src_vocab, tgt_vocab

class Encoder(nn.Module):
    """编码器-解码器架构的基本编码器接口"""
    def __init__(self, **kwargs):
        super(Encoder, self).__init__(**kwargs)

    def forward(self, X, *args):
        raise NotImplementedError

class Decoder(nn.Module):
    """编码器-解码器架构的基本解码器接口

    Defined in :numref:`sec_encoder-decoder`"""
    def __init__(self, **kwargs):
        super(Decoder, self).__init__(**kwargs)

    def init_state(self, enc_outputs, *args):
        raise NotImplementedError

    def forward(self, X, state):
        raise NotImplementedError

class EncoderDecoder(nn.Module):
    """编码器-解码器架构的基类

    Defined in :numref:`sec_encoder-decoder`"""

View on GitHub (pinned to e6b18ccea7)

Solutions

  1. Instantiate a concrete encoder: d2l.Seq2SeqEncoder(vocab_size, embed_size, num_hiddens, num_layers)
  2. In your subclass, define forward(self, X, *args) exactly (check spelling) at class-body indentation
  3. Smoke-test immediately after construction: model(enc_X, dec_X) on one batch to surface missing overrides early
  4. Lint with a check that MyEncoder.__dict__ contains 'forward' before use

Example fix

# before
enc = d2l.Encoder()
enc(X)  # NotImplementedError
# after
enc = d2l.Seq2SeqEncoder(vocab_size=10, embed_size=8, num_hiddens=16, num_layers=2)
enc(X)  # (output, state)
# or subclass
class MyEncoder(d2l.Encoder):
    def forward(self, X, *args):
        return X, None
Defensive patterns

Strategy: type-guard

Validate before calling

import d2l
assert type(encoder) is not d2l.Encoder and type(encoder).forward is not d2l.Encoder.forward, \
    'use a concrete Encoder subclass (e.g. Seq2SeqEncoder)'

Type guard

def is_concrete_encoder(obj) -> bool:
    return isinstance(obj, d2l.Encoder) and type(obj).forward is not d2l.Encoder.forward

Prevention

When it happens

Trigger: e = d2l.Encoder(); e(X); a subclass whose forward is misspelled (e.g. forwad) or defined outside the class body because of indentation, so nn.Module.__call__ falls through to the base method; passing a bare Encoder as the encoder member of EncoderDecoder and running a forward pass.

Common situations: D2L readers probing the interface; refactoring that swaps in the base class during tests; copy-paste from mxnet-flavored code where the subclass was written for nn.Block; IDE auto-import pulling d2l.Encoder instead of the concrete class.

Related errors


AI-assisted analysis of d2l-ai/d2l-zh@e6b18ccea7 (2026-08-14). Data as JSON: /api/errors/9ca6d8dcebb544f3. Report an issue: GitHub.