Model Architectures¶
TorchLingo provides two sequence-to-sequence architectures: a classic LSTM model and a modern Transformer. This page explains how each works and when to use them.
The Encoder-Decoder Framework¶
Both models follow the same high-level pattern:
flowchart LR
subgraph Encoder
A[Source Tokens] --> B[Embeddings]
B --> C[Encoder Layers]
C --> D[Context]
end
subgraph Decoder
D --> E[Decoder Layers]
F[Target Tokens] --> G[Embeddings]
G --> E
E --> H[Output Logits]
end
The difference is in how the encoder and decoder process sequences.
LSTM: The Classic Approach¶
How LSTMs Work¶
Long Short-Term Memory networks process sequences one step at a time, maintaining a "hidden state" that accumulates information:
Step 1: Read "I" → Update hidden state
Step 2: Read "love" → Update hidden state
Step 3: Read "cats" → Update hidden state (now contains "I love cats")
flowchart LR
A[I] --> B[LSTM Cell]
B --> C[hidden 1]
C --> D[love]
D --> E[LSTM Cell]
E --> F[hidden 2]
F --> G[cats]
G --> H[LSTM Cell]
H --> I[hidden 3]
TorchLingo's SimpleSeq2SeqLSTM¶
from torchlingo.models import SimpleSeq2SeqLSTM
model = SimpleSeq2SeqLSTM(
src_vocab_size=10000,
tgt_vocab_size=10000,
emb_dim=256, # Embedding dimension
hidden_dim=512, # LSTM hidden size
num_layers=2, # Stacked LSTM layers
dropout=0.1,
)
LSTM Architecture Diagram¶
┌─────────────────────────────────────────┐
│ ENCODER │
│ ┌───────────────────────────────────┐ │
│ │ Embedding Layer │ │
│ │ src_vocab_size → emb_dim │ │
│ └───────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────┐ │
│ │ LSTM Layers × N │ │
│ │ emb_dim → hidden_dim │ │
│ └───────────────────────────────────┘ │
│ ↓ │
│ (hidden_state, cell_state) │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ DECODER │
│ ┌───────────────────────────────────┐ │
│ │ Embedding Layer │ │
│ └───────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────┐ │
│ │ LSTM Layers × N │ │
│ │ (initialized with encoder state) │ │
│ └───────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────┐ │
│ │ Linear Output │ │
│ │ hidden_dim → tgt_vocab_size │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
Pros and Cons¶
| Pros | Cons |
|---|---|
| ✅ Simple to understand | ❌ Sequential (slow to train) |
| ✅ Few hyperparameters | ❌ Hard to capture long-range dependencies |
| ✅ Works on small datasets | ❌ Information bottleneck in hidden state |
Transformer: The Modern Standard¶
The Attention Revolution¶
Transformers process the entire sequence at once using attention:
Query: "What word should I focus on?"
Keys: [I, love, cats]
Values: [embed(I), embed(love), embed(cats)]
Attention weights: [0.1, 0.3, 0.6] ← Focus mostly on "cats"
Output: weighted combination of values
Self-Attention Explained¶
Self-attention lets each position look at all other positions:
# Simplified attention computation
Q = input @ W_q # Query projection
K = input @ W_k # Key projection
V = input @ W_v # Value projection
attention_weights = softmax(Q @ K.T / sqrt(d_k))
output = attention_weights @ V
For "I love cats", the word "love" can directly attend to both "I" and "cats".
Multi-Head Attention¶
Instead of one attention pattern, use multiple "heads" that learn different relationships:
Head 1: Subject-verb relationships
Head 2: Adjective-noun relationships
Head 3: Syntactic patterns
...
TorchLingo's SimpleTransformer¶
from torchlingo.models import SimpleTransformer
model = SimpleTransformer(
src_vocab_size=10000,
tgt_vocab_size=10000,
d_model=512, # Model dimension
n_heads=8, # Attention heads
num_encoder_layers=6, # Encoder depth
num_decoder_layers=6, # Decoder depth
d_ff=2048, # Feed-forward dimension
dropout=0.1,
)
Transformer Architecture Diagram¶
┌───────────────────────────────────────────────┐
│ ENCODER │
│ ┌─────────────────────────────────────────┐ │
│ │ Token Embedding + Positional Encoding │ │
│ └─────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────┐ │
│ │ Encoder Layer × N │ │
│ │ ┌───────────────────────────────────┐ │ │
│ │ │ Multi-Head Self-Attention │ │ │
│ │ └───────────────────────────────────┘ │ │
│ │ ┌───────────────────────────────────┐ │ │
│ │ │ Feed-Forward Network │ │ │
│ │ └───────────────────────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
└───────────────────────────────────────────────┘
↓
Encoder Output (Memory)
↓
┌───────────────────────────────────────────────┐
│ DECODER │
│ ┌─────────────────────────────────────────┐ │
│ │ Token Embedding + Positional Encoding │ │
│ └─────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────┐ │
│ │ Decoder Layer × N │ │
│ │ ┌───────────────────────────────────┐ │ │
│ │ │ Masked Multi-Head Self-Attention │ │ │
│ │ └───────────────────────────────────┘ │ │
│ │ ┌───────────────────────────────────┐ │ │
│ │ │ Cross-Attention (to encoder) │ │ │
│ │ └───────────────────────────────────┘ │ │
│ │ ┌───────────────────────────────────┐ │ │
│ │ │ Feed-Forward Network │ │ │
│ │ └───────────────────────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────┐ │
│ │ Linear → tgt_vocab_size │ │
│ └─────────────────────────────────────────┘ │
└───────────────────────────────────────────────┘
Positional Encoding¶
Since attention processes all positions simultaneously, the model has no sense of order. Positional encodings add position information:
TorchLingo uses the sinusoidal positional encoding from the original Transformer paper, added to the token embeddings:
from torchlingo.models.positional import SinusoidalPositionalEncoding
pos_enc = SinusoidalPositionalEncoding(d_model=512, max_seq_len=2048)
Sinusoidal encoding advantages:
- No learned parameters — produces valid values for any position
- For a fixed offset, encodings are related by a simple rotation, so the model can learn to attend by relative position
- The classic, well-understood baseline from "Attention Is All You Need"
Masking¶
Two types of masks in Transformers:
Padding Mask: Ignore PAD tokens
Causal Mask: Decoder can't see future tokens
Position 0: Can see [0]
Position 1: Can see [0, 1]
Position 2: Can see [0, 1, 2]
Position 3: Can see [0, 1, 2, 3]
Pros and Cons¶
| Pros | Cons |
|---|---|
| ✅ Parallel training (fast) | ❌ More hyperparameters |
| ✅ Captures long-range dependencies | ❌ Quadratic memory in sequence length |
| ✅ State-of-the-art quality | ❌ Needs more data |
Choosing a Model¶
Decision Guide¶
flowchart TD
A[Start] --> B{How much data?}
B -->|< 10K sentences| C[LSTM]
B -->|> 10K sentences| D{GPU available?}
D -->|No| C
D -->|Yes| E{Priority?}
E -->|Training speed| F[Transformer]
E -->|Simplicity| C
E -->|Best quality| F
Quick Comparison¶
| Aspect | LSTM | Transformer |
|---|---|---|
| Parameters | ~5-20M | ~20-100M |
| Training speed | Slow | Fast (parallel) |
| Inference speed | Fast | Medium |
| Memory usage | O(n) | O(n²) |
| Long sequences | Struggles | Handles well |
| Minimum data | ~5K pairs | ~50K pairs |
Configuration Examples¶
Tiny Model (Demo/Testing)¶
config = Config(
# Transformer
d_model=128,
n_heads=4,
num_encoder_layers=2,
num_decoder_layers=2,
d_ff=512,
)
# ~1M parameters, trains in seconds
Small Model (Learning)¶
config = Config(
d_model=256,
n_heads=8,
num_encoder_layers=4,
num_decoder_layers=4,
d_ff=1024,
)
# ~10M parameters, trains in minutes
Medium Model (Good Quality)¶
config = Config(
d_model=512,
n_heads=8,
num_encoder_layers=6,
num_decoder_layers=6,
d_ff=2048,
)
# ~60M parameters, trains in hours
Model Methods¶
Common Interface¶
Both models share a similar interface:
# Forward pass (training)
logits = model(src_batch, tgt_batch)
# Encode only (for inference)
memory = model.encode(src_batch)
# Decode step (for inference)
output = model.decode(tgt_batch, memory)
Saving and Loading¶
import torch
# Save
torch.save(model.state_dict(), "model.pt")
# Load
model.load_state_dict(torch.load("model.pt"))
Under the Hood¶
Embedding Scaling¶
TorchLingo scales embeddings by √d_model to prevent values from getting too small:
Weight Initialization¶
Xavier/Glorot initialization for stable training:
Next Steps¶
Now that you understand the models, learn how to train them: