Transformers in Machine Learning
The Transformer architecture, introduced in “Attention Is All You Need” (2017), revolutionized machine learning by replacing recurrence with self-attention. Today, Transformers are the dominant architecture in NLP, computer vision, audio, and increasingly in tabular data.
The Core Problem Transformers Solve
RNNs/LSTMs process sequences step by step — they can’t parallelize training and struggle to connect information from very distant positions. Transformers replace the sequential process with self-attention: every position can directly attend to every other position in a single operation.
Self-Attention
For each token, self-attention computes a weighted sum of all other tokens’ values, where weights are determined by query-key similarity:
Input sequence: "The cat sat on the mat"
For each word: Query (Q): "What am I looking for?" Key (K): "What do I contain?" Value (V): "What information do I pass on?"
Attention(Q, K, V) = softmax(QKᵀ / √dₖ) × V
The word "sat" attends strongly to "cat" (who sat?) and "mat" (sat where?)import torchimport torch.nn as nnimport math
class SelfAttention(nn.Module): def __init__(self, d_model, num_heads): super().__init__() self.num_heads = num_heads self.d_head = d_model // num_heads
self.W_q = nn.Linear(d_model, d_model) self.W_k = nn.Linear(d_model, d_model) self.W_v = nn.Linear(d_model, d_model) self.W_o = nn.Linear(d_model, d_model)
def forward(self, x, mask=None): B, T, C = x.shape
Q = self.W_q(x).view(B, T, self.num_heads, self.d_head).transpose(1, 2) K = self.W_k(x).view(B, T, self.num_heads, self.d_head).transpose(1, 2) V = self.W_v(x).view(B, T, self.num_heads, self.d_head).transpose(1, 2)
scores = (Q @ K.transpose(-2, -1)) / math.sqrt(self.d_head) if mask is not None: scores = scores.masked_fill(mask == 0, -1e9)
attn = torch.softmax(scores, dim=-1) out = attn @ V # (B, heads, T, d_head) out = out.transpose(1, 2).contiguous().view(B, T, C) return self.W_o(out)Transformer Block
A standard Transformer block consists of self-attention + feedforward network with residual connections and layer normalization:
class TransformerBlock(nn.Module): def __init__(self, d_model, num_heads, ff_dim, dropout=0.1): super().__init__() self.attention = SelfAttention(d_model, num_heads) self.norm1 = nn.LayerNorm(d_model) self.norm2 = nn.LayerNorm(d_model) self.ff = nn.Sequential( nn.Linear(d_model, ff_dim), nn.GELU(), nn.Dropout(dropout), nn.Linear(ff_dim, d_model), nn.Dropout(dropout) )
def forward(self, x, mask=None): x = self.norm1(x + self.attention(x, mask)) # Residual + attention x = self.norm2(x + self.ff(x)) # Residual + FFN return xPositional Encoding
Unlike RNNs, Transformers process all tokens simultaneously — they have no built-in notion of order. Positional encodings are added to token embeddings to inject position information:
class PositionalEncoding(nn.Module): def __init__(self, d_model, max_seq_len=5000): super().__init__() pe = torch.zeros(max_seq_len, d_model) position = torch.arange(max_seq_len).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) self.register_buffer('pe', pe)
def forward(self, x): return x + self.pe[:x.size(1)].unsqueeze(0)Transformer Families
Encoder-only (BERT-style): Bidirectional attention over the full sequence. Best for understanding tasks: classification, NER, question answering.
Decoder-only (GPT-style): Causal (masked) attention — each token attends only to past tokens. Best for generation: text completion, summarization, code generation.
Encoder-decoder (T5-style): Full encoder + causal decoder. Best for sequence-to-sequence: translation, summarization with fixed-length output.
Using Pretrained Transformers with HuggingFace
from transformers import AutoTokenizer, AutoModelForSequenceClassificationimport torch
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased", num_labels=3)
texts = ["I love this product!", "Terrible experience.", "It's okay."]inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt", max_length=128)
with torch.no_grad(): outputs = model(**inputs) predictions = outputs.logits.argmax(dim=-1)Vision Transformers (ViT)
Transformers now achieve state-of-the-art on image tasks by splitting images into 16×16 patches and treating them as “tokens”:
from torchvision.models import vit_b_16vit = vit_b_16(pretrained=True)Transformers are the unified architecture of modern AI — if you understand self-attention, you understand the core mechanism behind GPT, BERT, ViT, Whisper, DALL·E, and most state-of-the-art models.