Skip to content
AILinkDeepTech
Go back
Deep Learning Medium

Transformer Encoder Implementation in PyTorch

Abstract

A compact PyTorch implementation of a Transformer encoder with multi-head self-attention, sinusoidal positional encoding, feed-forward layers, residual connections, and padding masks.

Transformer Encoder Implementation in PyTorch

This implementation builds a Transformer encoder from core PyTorch modules. It includes multi-head self-attention, sinusoidal positional encoding, position-wise feed-forward networks, residual connections with layer normalization, and a padding mask.

import torch
import torch.nn as nn
import math

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super().__init__()
        assert d_model % num_heads == 0, "d_model must be divisible by num_heads"
        
        self.d_model = d_model
        self.num_heads = num_heads
        self.d_k = 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 scaled_dot_product_attention(self, Q, K, V, mask=None):
        scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
        
        if mask is not None:
            scores = scores.masked_fill(mask == 0, -1e9)
        
        attention_weights = torch.softmax(scores, dim=-1)
        return torch.matmul(attention_weights, V), attention_weights

    def forward(self, Q, K, V, mask=None):
        batch_size = Q.size(0)
        
        Q = self.W_q(Q).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
        K = self.W_k(K).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
        V = self.W_v(V).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
        
        output, attention = self.scaled_dot_product_attention(Q, K, V, mask)
        
        output = output.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)
        return self.W_o(output)

class PositionalEncoding(nn.Module):
    def __init__(self, d_model, max_seq_length=5000):
        super().__init__()
        
        pe = torch.zeros(max_seq_length, d_model)
        position = torch.arange(0, max_seq_length, dtype=torch.float).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
        
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0)
        
        self.register_buffer('pe', pe)

    def forward(self, x):
        return x + self.pe[:, :x.size(1)]

class TransformerEncoderLayer(nn.Module):
    def __init__(self, d_model, num_heads, d_ff, dropout=0.1):
        super().__init__()
        
        self.self_attention = MultiHeadAttention(d_model, num_heads)
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.dropout = nn.Dropout(dropout)
        
        self.feed_forward = nn.Sequential(
            nn.Linear(d_model, d_ff),
            nn.ReLU(),
            nn.Dropout(dropout),
            nn.Linear(d_ff, d_model)
        )

    def forward(self, x, mask=None):
        attn_output = self.self_attention(x, x, x, mask)
        x = self.norm1(x + self.dropout(attn_output))
        
        ff_output = self.feed_forward(x)
        x = self.norm2(x + self.dropout(ff_output))
        
        return x

class Transformer(nn.Module):
    def __init__(self, d_model, num_heads, num_layers, d_ff, max_seq_length,
                 vocab_size, dropout=0.1):
        super().__init__()
        
        self.embedding = nn.Embedding(vocab_size, d_model)
        self.positional_encoding = PositionalEncoding(d_model, max_seq_length)
        
        self.encoder_layers = nn.ModuleList([
            TransformerEncoderLayer(d_model, num_heads, d_ff, dropout)
            for _ in range(num_layers)
        ])
        
        self.dropout = nn.Dropout(dropout)
        self.final_layer = nn.Linear(d_model, vocab_size)

    def forward(self, x, mask=None):
        x = self.embedding(x)
        x = self.positional_encoding(x)
        x = self.dropout(x)
        
        for encoder_layer in self.encoder_layers:
            x = encoder_layer(x, mask)
        
        output = self.final_layer(x)
        return output

def create_padding_mask(seq, pad_idx=0):
    return (seq != pad_idx).unsqueeze(1).unsqueeze(2)

# Test the implementation
if __name__ == "__main__":
    # Model parameters
    d_model = 512
    num_heads = 8
    num_layers = 6
    d_ff = 2048
    max_seq_length = 100
    vocab_size = 1000
    batch_size = 16
    seq_length = 30

    print("Initializing Transformer model...")
    
    # Initialize model
    model = Transformer(
        d_model=d_model,
        num_heads=num_heads,
        num_layers=num_layers,
        d_ff=d_ff,
        max_seq_length=max_seq_length,
        vocab_size=vocab_size
    )

    print("Creating test input...")
    
    # Create dummy input data
    input_data = torch.randint(0, vocab_size, (batch_size, seq_length))
    
    # Create padding mask
    mask = create_padding_mask(input_data)

    print("Running forward pass...")
    
    output = model(input_data, mask)
    
    print(f"\nTest Results:")
    print(f"Input shape: {input_data.shape}")
    print(f"Output shape: {output.shape}")

    print("\nTesting individual components...")

    # Test attention
    mha = MultiHeadAttention(d_model, num_heads)
    x = torch.randn(batch_size, seq_length, d_model)
    attention_output = mha(x, x, x)
    print(f"Multi-head attention output shape: {attention_output.shape}")

    # Test positional encoding
    pe = PositionalEncoding(d_model)
    pos_encoding_output = pe(x)
    print(f"Positional encoding output shape: {pos_encoding_output.shape}")

    print("\nAll tests completed successfully!")


Cite this Explanation

@article{ailinkdeeptech2026transformeralgo,
  title={Transformer Encoder Implementation in PyTorch},
  author={AILinkDeepTech},
  journal={AILinkDeepTech Algorithm Explanations},
  year={2026},
  url={https://ailinkdeeptech.com/research/transformer_algo}
}

Related Explanations