Denoising Objectives › BART-Style Combined Denoising
Language AI HandbookAll chapters Denoising Objectives › BART-Style Combined DenoisingOne section · Sections in this chapter8 / 15 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
BART combines multiple corruption types to create a versatile denoising objective. The original BART paper explored five transformations:
- Token masking: Replace tokens with
[MASK](similar to BERT) - Token deletion: Remove tokens entirely
- Text infilling: Replace spans with single
[MASK]tokens - Sentence permutation: Shuffle sentence order
- Document rotation: Rotate document around random point
The best-performing configuration used text infilling as the primary corruption, combined with sentence permutation. This combination forces the model to learn both local (word-level) and global (document-level) structure. Text infilling trains the decoder to generate variable-length continuations that fill in masked spans, which is a direct precursor to the generation capability needed for summarization. Sentence permutation trains the encoder to build representations that capture inter-sentence relationships, which supports tasks like coherence scoring and multi-document reasoning. Together, they ensure that neither local nor global language understanding is neglected during pretraining.
class BARTCorruptor:
"""
Apply BART-style denoising corruption to text.
Combines multiple corruption strategies:
- Text infilling (spans replaced with single mask)
- Sentence permutation (reorder sentences)
"""
def __init__(
self,
mask_prob=0.30,
mean_span_length=3,
permute_sentences=True,
mask_token="[MASK]",
):
self.mask_prob = mask_prob
self.mean_span_length = mean_span_length
self.permute_sentences = permute_sentences
self.mask_token = mask_token
def _split_sentences(self, tokens):
"""Split token list into sentences (simple period-based)."""
sentences = []
current = []
for token in tokens:
current.append(token)
if (
token.endswith(".")
or token.endswith("!")
or token.endswith("?")
):
sentences.append(current)
current = []
if current:
sentences.append(current)
return sentences
def _infill_tokens(self, tokens):
"""Apply text infilling to token list."""
n = len(tokens)
if n == 0:
return tokens
num_to_mask = max(1, int(n * self.mask_prob))
# Sample span lengths
p = 1 / self.mean_span_length
mask = np.zeros(n, dtype=bool)
span_positions = []
total_masked = 0
attempts = 0
while total_masked < num_to_mask and attempts < 100:
attempts += 1
span_length = np.random.geometric(p)
span_length = min(span_length, num_to_mask - total_masked, n)
valid_starts = [
i
for i in range(n - span_length + 1)
if not any(mask[i : i + span_length])
]
if not valid_starts:
continue
start = np.random.choice(valid_starts)
mask[start : start + span_length] = True
span_positions.append((start, start + span_length))
total_masked += span_length
span_positions.sort()
# Build result
result = []
last_end = 0
for start, end in span_positions:
result.extend(tokens[last_end:start])
result.append(self.mask_token)
last_end = end
result.extend(tokens[last_end:])
return result
def corrupt(self, tokens):
"""
Apply BART-style corruption.
Args:
tokens: List of string tokens
Returns:
dict with 'input' (corrupted) and 'target' (original) token lists
"""
working_tokens = list(tokens)
# Step 1: Sentence permutation (if enabled and multiple sentences)
if self.permute_sentences:
sentences = self._split_sentences(working_tokens)
if len(sentences) > 1:
order = np.random.permutation(len(sentences))
working_tokens = []
for i in order:
working_tokens.extend(sentences[i])
# Step 2: Text infilling
corrupted = self._infill_tokens(working_tokens)
return {"input": corrupted, "target": list(tokens)}# Demonstrate BART corruption
document = """The transformer changed NLP. Attention is all you need.
Models became larger. Performance improved dramatically."""
tokens = document.split()
corruptor = BARTCorruptor(
mask_prob=0.30, mean_span_length=3, permute_sentences=True
)
result = corruptor.corrupt(tokens)Original: The transformer changed NLP. Attention is all you need. Models became larger. Performance improved dramatically. Corrupted (13 tokens): Attention is all [MASK] need. Models became larger. The transformer changed [MASK] dramatically. Compression: 15 -> 13 tokens (13% reduction)
The corrupted version demonstrates both transformations working together. Sentences appear in a different order, and multiple spans have been replaced with [MASK] tokens. The sequence is noticeably shorter because each masked span, regardless of how many tokens it contained, becomes a single placeholder. This compression is a key efficiency advantage of text infilling: the encoder processes fewer tokens while the decoder still generates the full original.

The compression from text infilling provides computational savings during training. The encoder processes shorter sequences, reducing the quadratic attention cost, while the decoder still learns to generate the full original sequence. This asymmetry is intentional: it makes encoder computation cheap while keeping decoder training rich. For long documents, where encoder self-attention over the full sequence would be prohibitively expensive, this compression increases the number of training examples the model can process per hour.