Transformer¶
Simple transformer-based sequence-to-sequence model with sinusoidal positional encoding.
Overview¶
SimpleTransformer implements the encoder-decoder Transformer architecture from "Attention Is All You Need" (Vaswani et al., 2017), using the paper's sinusoidal positional encoding.
Architecture¶
┌─────────────────────────────────────────────────┐
│ ENCODER │
│ ┌───────────────────────────────────────────┐ │
│ │ Token Embedding + Sinusoidal Position │ │
│ │ src_vocab_size → d_model │ │
│ └───────────────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────────┐ │
│ │ Transformer Encoder × N │ │
│ │ • Multi-Head Self-Attention │ │
│ │ • Feed-Forward Network │ │
│ │ • LayerNorm + Residual │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
↓
Encoder Output (Memory)
↓
┌─────────────────────────────────────────────────┐
│ DECODER │
│ ┌───────────────────────────────────────────┐ │
│ │ Token Embedding + Sinusoidal Position │ │
│ │ tgt_vocab_size → d_model │ │
│ └───────────────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────────┐ │
│ │ Transformer Decoder × N │ │
│ │ • Masked Multi-Head Self-Attention │ │
│ │ • Cross-Attention (to encoder) │ │
│ │ • Feed-Forward Network │ │
│ │ • LayerNorm + Residual │ │
│ └───────────────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────────┐ │
│ │ Linear Generator │ │
│ │ d_model → tgt_vocab_size │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
Quick Start¶
from torchlingo.models import SimpleTransformer
model = SimpleTransformer(
src_vocab_size=10000,
tgt_vocab_size=10000,
d_model=512,
n_heads=8,
num_encoder_layers=6,
num_decoder_layers=6,
)
# Training
logits = model(src_batch, tgt_batch) # [batch, tgt_len, vocab]
# Inference
memory = model.encode(src_batch)
logits = model.decode(tgt_batch, memory)
API Reference¶
SimpleTransformer
¶
SimpleTransformer(src_vocab_size: int, tgt_vocab_size: int, d_model: Optional[int] = None, n_heads: Optional[int] = None, num_encoder_layers: Optional[int] = None, num_decoder_layers: Optional[int] = None, d_ff: Optional[int] = None, max_seq_length: Optional[int] = None, dropout: Optional[float] = None, pad_idx: Optional[int] = None, config: Optional[Config] = None)
Bases: Module
Transformer encoder-decoder model with sinusoidal positional encoding.
A standard transformer architecture combining an encoder and decoder, each composed of stacked multi-head self-attention and feed-forward layers. Uses the fixed sinusoidal positional encoding from Vaswani et al. (2017). Embeddings are scaled by sqrt(d_model) to prevent vanishing gradients.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src_vocab_size
|
int
|
Size of the source vocabulary. |
required |
tgt_vocab_size
|
int
|
Size of the target vocabulary. |
required |
d_model
|
int
|
Model hidden dimension. Defaults to 512. |
None
|
n_heads
|
int
|
Number of attention heads. Defaults to 8. |
None
|
num_encoder_layers
|
int
|
Number of encoder transformer blocks. Defaults to 6. |
None
|
num_decoder_layers
|
int
|
Number of decoder transformer blocks. Defaults to 6. |
None
|
d_ff
|
int
|
Feed-forward inner dimension. Defaults to 2048. |
None
|
max_seq_length
|
int
|
Maximum sequence length for the positional encoding table. Defaults to 512. |
None
|
dropout
|
float
|
Dropout rate throughout the model. Defaults to 0.1. |
None
|
pad_idx
|
int
|
Padding token index. Falls back to config.pad_idx. |
None
|
config
|
Config
|
Configuration object. Defaults to default config. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
d_model |
int
|
Model dimension. |
max_seq_length |
int
|
Maximum sequence length. |
pad_idx |
int
|
Resolved padding index. |
src_tok_emb |
Embedding
|
Source token embedding layer. |
tgt_tok_emb |
Embedding
|
Target token embedding layer. |
pos_encoding |
SinusoidalPositionalEncoding
|
Positional encoding module. |
transformer |
Transformer
|
PyTorch transformer with encoder and decoder. |
generator |
Linear
|
Output projection to target vocabulary logits. |
Source code in src/torchlingo/models/transformer_simple.py
forward
¶
forward(src: Tensor, tgt: Tensor, src_key_padding_mask: Optional[Tensor] = None, tgt_key_padding_mask: Optional[Tensor] = None, tgt_mask: Optional[Tensor] = None) -> Tensor
Encode source and decode target in a single forward pass.
Automatically generates padding and causal masks if not provided. Calls encode() to process source sequences, then decode() to generate target sequence predictions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src
|
Tensor
|
Source token indices of shape (batch_size, src_len). |
required |
tgt
|
Tensor
|
Target token indices of shape (batch_size, tgt_len). |
required |
src_key_padding_mask
|
Tensor
|
Boolean mask for source padding. If None, generated automatically from padding index. Defaults to None. |
None
|
tgt_key_padding_mask
|
Tensor
|
Boolean mask for target padding. If None, generated automatically from padding index. Defaults to None. |
None
|
tgt_mask
|
Tensor
|
Causal mask for target self-attention. If None, generated automatically. Defaults to None. |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
torch.Tensor: Logits of shape (batch_size, tgt_len, tgt_vocab_size). |
Source code in src/torchlingo/models/transformer_simple.py
encode
¶
Encode source sequence using the transformer encoder.
Embeds source tokens, adds sinusoidal positional encodings, then passes the result through the transformer encoder stack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src
|
Tensor
|
Source token indices of shape (batch_size, src_len). |
required |
src_key_padding_mask
|
Tensor
|
Boolean mask where True indicates padding positions to ignore. Shape (batch_size, src_len). Defaults to None. |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
torch.Tensor: Encoded source representation of shape (batch_size, src_len, d_model). |
Source code in src/torchlingo/models/transformer_simple.py
decode
¶
decode(tgt: Tensor, memory: Tensor, src_key_padding_mask: Optional[Tensor] = None, tgt_key_padding_mask: Optional[Tensor] = None, tgt_mask: Optional[Tensor] = None) -> Tensor
Decode target sequence using the transformer decoder and encoder output.
Embeds target tokens, adds sinusoidal positional encodings, then passes them through the transformer decoder with cross-attention to the encoder output. The decoder is typically run with a causal mask to prevent attending to future tokens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tgt
|
Tensor
|
Target token indices of shape (batch_size, tgt_len). |
required |
memory
|
Tensor
|
Encoded source from encoder output, shape (batch_size, src_len, d_model). |
required |
src_key_padding_mask
|
Tensor
|
Mask for encoder output padding. Shape (batch_size, src_len). Defaults to None. |
None
|
tgt_key_padding_mask
|
Tensor
|
Mask for target padding. Shape (batch_size, tgt_len). Defaults to None. |
None
|
tgt_mask
|
Tensor
|
Causal mask for target self-attention. Shape (tgt_len, tgt_len). Defaults to None. |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
torch.Tensor: Decoder output logits of shape (batch_size, tgt_len, tgt_vocab_size). |
Source code in src/torchlingo/models/transformer_simple.py
Constructor Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
src_vocab_size |
int | required | Source vocabulary size |
tgt_vocab_size |
int | required | Target vocabulary size |
d_model |
int | 512 | Model hidden dimension |
n_heads |
int | 8 | Number of attention heads |
num_encoder_layers |
int | 6 | Encoder transformer blocks |
num_decoder_layers |
int | 6 | Decoder transformer blocks |
d_ff |
int | 2048 | Feed-forward inner dimension |
max_seq_length |
int | 512 | Maximum sequence length |
dropout |
float | 0.1 | Dropout rate |
pad_idx |
int | 0 | Padding token index |
config |
Config | None | Configuration object |
Examples¶
Basic Training¶
import torch
from torchlingo.models import SimpleTransformer
from torchlingo.config import Config
config = Config(d_model=256, n_heads=8)
model = SimpleTransformer(
src_vocab_size=10000,
tgt_vocab_size=10000,
config=config,
)
# Dummy data
src = torch.randint(0, 10000, (32, 20)) # [batch, src_len]
tgt = torch.randint(0, 10000, (32, 25)) # [batch, tgt_len]
# Forward pass
logits = model(src, tgt[:, :-1]) # [32, 24, 10000]
# Compute loss
criterion = torch.nn.CrossEntropyLoss(ignore_index=0)
loss = criterion(
logits.reshape(-1, logits.size(-1)),
tgt[:, 1:].reshape(-1)
)
Inference (Greedy Decoding)¶
def greedy_decode(model, src, tgt_vocab, max_len=50, device="cpu"):
model.eval()
src = src.to(device)
# Encode source
memory = model.encode(src)
# Start with SOS
ys = torch.tensor([[tgt_vocab.sos_idx]], device=device)
for _ in range(max_len):
logits = model.decode(ys, memory)
next_token = logits[:, -1, :].argmax(dim=-1, keepdim=True)
ys = torch.cat([ys, next_token], dim=1)
if next_token.item() == tgt_vocab.eos_idx:
break
return ys[0].tolist()
Custom Masking¶
# Manual padding mask
src_pad_mask = (src == pad_idx) # True where padding
# Manual causal mask
tgt_len = tgt.size(1)
causal_mask = torch.triu(
torch.ones(tgt_len, tgt_len, dtype=torch.bool),
diagonal=1
)
logits = model(
src, tgt,
src_key_padding_mask=src_pad_mask,
tgt_mask=causal_mask,
)
Key Features¶
Sinusoidal Positional Encoding¶
Fixed sine/cosine waves of geometrically increasing wavelengths are added to the token embeddings:
- No learned parameters; valid for any position
- Encodings for nearby positions are related by simple rotations, which helps the model attend by relative offset
- Matches the original "Attention Is All You Need" recipe
Automatic Masking¶
The model automatically generates:
- Padding masks: Prevent attention to PAD tokens
- Causal masks: Prevent decoder from seeing future tokens
Embedding Scaling¶
Embeddings are scaled by √d_model to maintain variance:
Xavier Initialization¶
Weights are initialized using Xavier uniform for stable training:
Model Variants¶
Tiny (Demo/Testing)¶
model = SimpleTransformer(
src_vocab_size, tgt_vocab_size,
d_model=64, n_heads=2,
num_encoder_layers=1, num_decoder_layers=1,
)
# ~500K params, trains in seconds
Base¶
model = SimpleTransformer(
src_vocab_size, tgt_vocab_size,
d_model=512, n_heads=8,
num_encoder_layers=6, num_decoder_layers=6,
)
# ~65M params, good quality
Large¶
model = SimpleTransformer(
src_vocab_size, tgt_vocab_size,
d_model=1024, n_heads=16,
num_encoder_layers=6, num_decoder_layers=6,
d_ff=4096,
)
# ~200M params, high quality
Computational Considerations¶
| Aspect | Complexity |
|---|---|
| Self-attention | O(n² × d) |
| Memory | O(n² + n × d) |
| Parameters | O(L × d²) |
Where n = sequence length, d = d_model, L = num layers.
Long Sequences
Attention has O(n²) complexity. For very long sequences (>1000 tokens), consider using flash attention or other efficient attention implementations.