DeBERTa v1 / v2 / v3 (text encoder)¶
Microsoft's DeBERTa family in pure Keras 3: the disentangled-attention bidirectional text encoder, in its three generations (v1, v2, v3), each with the masked-LM, sequence-classification, token-classification, question-answering, and multiple-choice heads. One implementation per version runs unmodified on TensorFlow / Torch / JAX, with bit-close parity to Hugging Face on real checkpoints (see below).
Papers: DeBERTa: Decoding-enhanced BERT with Disentangled Attention (v1 / v2) · DeBERTaV3: ELECTRA-Style Pre-Training with Gradient-Disentangled Embedding Sharing (v3)
Each generation lives in its own package with the same set of model classes plus a tokenizer; only the module path and the class prefix change (v1 has no multiple-choice head):
| Task | v1: kerasformers.models.deberta |
v2, kerasformers.models.deberta_v2 |
v3, kerasformers.models.deberta_v3 |
Output |
|---|---|---|---|---|
| Backbone | DebertaModel |
DebertaV2Model |
DebertaV3Model |
{"last_hidden_state": (B, L, embed_dim)} |
| Masked LM | DebertaMaskedLM |
DebertaV2MaskedLM |
DebertaV3MaskedLM |
MLM logits (B, L, vocab_size) |
| Sequence classify | DebertaSequenceClassify |
DebertaV2SequenceClassify |
DebertaV3SequenceClassify |
(B, num_classes) |
| Token classify | DebertaTokenClassify |
DebertaV2TokenClassify |
DebertaV3TokenClassify |
(B, L, num_classes) |
| Question answering | DebertaQnA |
DebertaV2QnA |
DebertaV3QnA |
{"start_logits": (B, L), "end_logits": (B, L)} |
| Multiple choice | : | DebertaV2MultipleChoice |
DebertaV3MultipleChoice |
(B, num_choices) |
| Tokenizer | DebertaTokenizer (byte-level BPE) |
DebertaV2Tokenizer (SentencePiece) |
DebertaV3Tokenizer (SentencePiece) |
input_ids / attention_mask / token_type_ids |
All models are functional FunctionalBaseModels; the head classes compose the matching
backbone. Unlike BERT, DeBERTa has no pooler and no next-sentence head: the
backbone returns only last_hidden_state, and the sequence/multiple-choice heads
attach DeBERTa's context pooler (a dense + gelu over the [CLS] token). The
masked-LM head is part of the pretrained checkpoint; the other task heads are
randomly initialized for the official release (ready for fine-tuning) and load
trained weights from a hf: fine-tune.
Loading¶
Two paths, both via from_weights:
- Official release variant:
from_weights("deberta_base")downloads the kerasformers-release.weights.h5. hf:checkpoint / community fine-tune:from_weights("hf:org/repo")reads the repo'sconfig.json(architecture +num_labels) and loads the checkpoint, including a fine-tuned classifier head.
from kerasformers.models.deberta_v3 import DebertaV3Model, DebertaV3Tokenizer
model = DebertaV3Model.from_weights("deberta_v3_base")
tokenizer = DebertaV3Tokenizer.from_weights("deberta_v3_base")
out = model(tokenizer("Hello, world."))
out["last_hidden_state"] # (1, L, 768)
Available variants¶
| Version | Variant | vocab | layers / dim |
|---|---|---|---|
| v1 | deberta_base |
50265 | 12 / 768 |
| v1 | deberta_large |
50265 | 24 / 1024 |
| v2 | deberta_v2_xlarge |
128100 | 24 / 1536 |
| v2 | deberta_v2_xxlarge |
128100 | 48 / 1536 |
| v3 | deberta_v3_xsmall |
128100 | 12 / 384 |
| v3 | deberta_v3_small |
128100 | 6 / 768 |
| v3 | deberta_v3_base |
128100 | 12 / 768 |
| v3 | deberta_v3_large |
128100 | 24 / 1024 |
Verified parity¶
Validated against the Hugging Face reference (eager attention) on a real forward pass, including a padded sequence:
| Model | Checkpoint | max |Δ| |
|---|---|---|
DebertaModel |
microsoft/deberta-base |
2.6e-5 |
DebertaMaskedLM |
microsoft/deberta-base |
4.8e-5 |
DebertaV2Model |
microsoft/deberta-v2-xlarge |
4.8e-7 |
DebertaV2MaskedLM |
microsoft/deberta-v2-xlarge |
1.8e-7 |
DebertaV3Model |
microsoft/deberta-v3-base |
9.7e-5 |
DebertaV3Model |
microsoft/deberta-v3-large |
2.9e-6 |
DeBERTa-v3 checkpoints ship as float16. Load the HF reference with
from_pretrained(..., dtype=torch.float32)to compare like-for-like: otherwise HF runs the forward in fp16 and the ~0.07 gap is the fp16/fp32 difference, not a model error (Keras runs in fp32, so it is actually closer to the fp64 ideal).
Forward pass¶
The models take a dict of token ids, an attention mask, and segment ids: exactly
what the tokenizer returns (segment ids are always 0; DeBERTa has no token-type
embeddings and ignores them, they are accepted for API parity):
inputs = {
"input_ids": input_ids, # (B, L) int
"attention_mask": attention_mask, # (B, L) int: 1 keep, 0 pad
"token_type_ids": token_type_ids, # (B, L) int: all 0 (unused)
}
DebertaV3Model.from_weights("deberta_v3_base")(inputs)["last_hidden_state"]
These are token-id models: no spatial H/W axes, so channels_first/last
does not apply.
Fill-mask¶
from kerasformers.models.deberta_v3 import DebertaV3MaskedLM, DebertaV3Tokenizer
mlm = DebertaV3MaskedLM.from_weights("deberta_v3_base")
tokenizer = DebertaV3Tokenizer.from_weights("deberta_v3_base")
inputs = tokenizer("The capital of France is [MASK].")
logits = mlm(inputs) # (1, L, vocab_size)
mask = int((inputs["input_ids"][0] == tokenizer.mask_token_id).argmax())
print(tokenizer.decode([int(logits[0, mask].argmax())]))
Classification (community fine-tunes)¶
from kerasformers.models.deberta_v3 import (
DebertaV3SequenceClassify,
DebertaV3TokenClassify,
)
# natural-language inference / zero-shot (3 labels)
nli = DebertaV3SequenceClassify.from_weights("hf:microsoft/deberta-v3-base") # + a fine-tune
# named-entity recognition
ner = DebertaV3TokenClassify.from_weights("hf:org/deberta-v3-ner")
num_classes is read from the repo's config, so the head matches the fine-tune.
Other task heads¶
from kerasformers.models.deberta_v3 import DebertaV3QnA, DebertaV3MultipleChoice
# extractive QA: start/end span logits
qa = DebertaV3QnA.from_weights("hf:org/deberta-v3-squad")
out = qa(tokenizer("Where is Paris?", text_pair="Paris is in France."))
out["start_logits"] # (B, L) out["end_logits"] # (B, L)
# multiple choice: inputs are (B, num_choices, seq); fix num_choices at build
mc = DebertaV3MultipleChoice.from_weights("hf:org/deberta-v3-swag", num_choices=4)
*MultipleChoice takes a static num_choices (the choice axis is folded into the
batch through the shared backbone, then back out); its classifier head is
shape-independent of num_choices, so the same weights load for any value.
Tokenizers¶
- v1:
DebertaTokenizeris a byte-level BPE tokenizer (vocab.json+merges.txt, like GPT-2 / RoBERTa) but with BERT-style specials ([CLS] A [SEP], and[CLS] A [SEP] [SEP] B [SEP]for pairs). - v2 / v3:
DebertaV2Tokenizer/DebertaV3Tokenizerare SentencePiece Unigram tokenizers (spm.model, 128 100 pieces, no fairseq id offset) with[CLS] A [SEP]/[CLS] A [SEP] B [SEP]post-processing. v3 differs from v2 only in the underlyingspm.model.
All return the input_ids / attention_mask / token_type_ids dict the models
consume, and reproduce Hugging Face's ids exactly (single, pair, and
whitespace-heavy inputs).
Architecture notes¶
DeBERTa replaces BERT's absolute-position embeddings with disentangled
attention: each token is represented by separate content and (relative)
position vectors, and the attention score sums content→content,
content→position (c2p), and position→content (p2c) terms, scaled by
1/sqrt(head_dim · (1 + #pos_att_type)). Position information enters only through
attention: the input embeddings are word embeddings + LayerNorm only (no
absolute-position or token-type embeddings).
- v1: fused
in_projquery/key/value with separate query/value biases, and dedicatedpos_proj(c2p) /pos_q_proj(p2c) projections over a raw relative-position embedding table (rel[i,j] = i − j).layer_norm_eps = 1e-7. - v2: separate
query_proj/key_proj/value_proj; log-bucketed relative positions (position_buckets = 256) so a small table spans long sequences;share_att_keyreuses the content projections for the relative terms; a LayerNorm on the relative embeddings (norm_rel_ebd); and a single depthwise-style convolution (conv_kernel_size = 3) after the first encoder layer. SentencePiece vocabulary (128 100). - v3: the v2 architecture (HF
model_type = "deberta-v2", so it reuses the v2 backbone) without the convolution, pretrained ELECTRA-style with gradient-disentangled embedding sharing. Only the backbone is ported; the replaced-token-detection and mask-prediction heads are discriminator-only and not used for the encoder.
Constructor arguments follow the kerasformers convention: embed_dim,
num_layers, num_heads, mlp_dim (plus vocab_size,
max_position_embeddings, max_relative_positions, pos_att_type,
hidden_act, layer_norm_eps, pad_token_id; v2 / v3 add position_buckets,
norm_rel_ebd, conv_kernel_size, conv_act). Each
convert_deberta*_hf_to_keras.py maps the HF checkpoint's weights to Keras.
Citation¶
@inproceedings{he2021deberta, title={DeBERTa: Decoding-enhanced BERT with Disentangled Attention}, author={He, Pengcheng and Liu, Xiaodong and Gao, Jianfeng and Chen, Weizhu}, booktitle={ICLR}, year={2021}}
@inproceedings{he2023debertav3, title={DeBERTaV3: Improving DeBERTa using ELECTRA-Style Pre-Training with Gradient-Disentangled Embedding Sharing}, author={He, Pengcheng and Gao, Jianfeng and Chen, Weizhu}, booktitle={ICLR}, year={2023}}