En-Vi-Translator / models_best /positional_encoding.py
TVQuyet05
init
923f623
Raw
History Blame Contribute Delete
2.89 kB
"""
Sinusoidal Positional Encoding
"""
import math
import torch
import torch.nn as nn
class PositionalEncoding(nn.Module):
"""
Sinusoidal Positional Encoding
PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
"""
def __init__(self, d_model: int, max_len: int = 5000, dropout: float = 0.1):
"""
Args:
d_model: Model dimension
max_len: Maximum sequence length
dropout: Dropout rate
"""
super().__init__()
self.dropout = nn.Dropout(dropout) if dropout > 0 else None
# Create positional encoding matrix
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
# Compute the div_term: 10000^(2i/d_model)
div_term = torch.exp(
torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)
)
# Apply sine to even indices
pe[:, 0::2] = torch.sin(position * div_term)
# Apply cosine to odd indices
if d_model % 2 == 0:
pe[:, 1::2] = torch.cos(position * div_term)
else:
# Handle odd d_model
pe[:, 1::2] = torch.cos(position * div_term[:-1])
# Add batch dimension: [1, max_len, d_model]
pe = pe.unsqueeze(0)
# Register as buffer (not a parameter, but part of state_dict)
self.register_buffer('pe', pe)
def forward(self, x):
"""
Args:
x: [batch_size, seq_len, d_model]
Returns:
x with positional encoding added: [batch_size, seq_len, d_model]
"""
seq_len = x.size(1)
x = x + self.pe[:, :seq_len, :]
if self.dropout is not None:
x = self.dropout(x)
return x
class LearnedPositionalEncoding(nn.Module):
"""
Learned Positional Encoding (alternative to sinusoidal)
Can potentially learn better position representations for specific tasks
"""
def __init__(self, d_model: int, max_len: int = 5000, dropout: float = 0.1):
"""
Args:
d_model: Model dimension
max_len: Maximum sequence length
dropout: Dropout rate
"""
super().__init__()
self.dropout = nn.Dropout(dropout) if dropout > 0 else None
self.pe = nn.Parameter(torch.randn(1, max_len, d_model) * 0.02)
def forward(self, x):
"""
Args:
x: [batch_size, seq_len, d_model]
Returns:
x with positional encoding added: [batch_size, seq_len, d_model]
"""
seq_len = x.size(1)
x = x + self.pe[:, :seq_len, :]
if self.dropout is not None:
x = self.dropout(x)
return x