| |
| |
| |
| |
| |
|
|
| from typing import Optional |
|
|
| import math |
| import torch |
| import torch.nn as nn |
| import torch.nn.functional as F |
| from . import TransformerEncoderLayer, LayerNorm |
|
|
|
|
| def init_bert_params(module): |
| if not getattr(module, 'can_global_init', True): |
| return |
| def normal_(data): |
| data.copy_( |
| data.cpu().normal_(mean=0.0, std=0.02).to(data.device) |
| ) |
| if isinstance(module, nn.Linear): |
| normal_(module.weight.data) |
| if module.bias is not None: |
| module.bias.data.zero_() |
| if isinstance(module, nn.Embedding): |
| normal_(module.weight.data) |
| if module.padding_idx is not None: |
| module.weight.data[module.padding_idx].zero_() |
|
|
|
|
| def relative_position_bucket(relative_position, num_buckets=32, max_distance=128): |
| sign = torch.sign(relative_position) |
| num_buckets //= 2 |
| n = torch.abs(relative_position) |
|
|
| |
| max_exact = num_buckets // 2 |
| is_small = n < max_exact |
| max_bucket_val = num_buckets - 1 - max_exact |
| |
| val_if_large = max_exact + torch.ceil( |
| torch.log(n.float() / max_exact) / math.log((max_distance - 1) / max_exact) * (max_bucket_val) |
| ).long() |
| val_if_large = torch.min(val_if_large, torch.full_like(val_if_large, num_buckets - 1)) |
| ret = torch.where(is_small, n, val_if_large) * sign |
| return ret |
|
|
|
|
| class TransformerEncoder(nn.Module): |
| def __init__( |
| self, |
| encoder_layers: int = 6, |
| embed_dim: int = 768, |
| ffn_embed_dim: int = 3072, |
| attention_heads: int = 8, |
| emb_dropout: float = 0.1, |
| dropout: float = 0.1, |
| attention_dropout: float = 0.1, |
| activation_dropout: float = 0.0, |
| max_seq_len: int = 256, |
| activation_fn: str = "gelu", |
| rel_pos: bool = True, |
| rel_pos_bins: int = 32, |
| max_rel_pos: int = 128, |
| post_ln: bool = False, |
| ) -> None: |
|
|
| super().__init__() |
| self.emb_dropout = emb_dropout |
| self.max_seq_len = max_seq_len |
| self.embed_dim = embed_dim |
| self.attention_heads = attention_heads |
| self.emb_layer_norm = LayerNorm(self.embed_dim) |
| if not post_ln: |
| self.final_layer_norm = LayerNorm(self.embed_dim) |
| else: |
| self.final_layer_norm = None |
|
|
| self.layers = nn.ModuleList( |
| [ |
| TransformerEncoderLayer( |
| embed_dim=self.embed_dim, |
| ffn_embed_dim=ffn_embed_dim, |
| attention_heads=attention_heads, |
| dropout=dropout, |
| attention_dropout=attention_dropout, |
| activation_dropout=activation_dropout, |
| activation_fn=activation_fn, |
| post_ln=post_ln, |
| |
| ) |
| for _ in range(encoder_layers) |
| ] |
| ) |
|
|
| self.rel_pos = rel_pos |
|
|
| if self.rel_pos: |
| assert rel_pos_bins % 2 == 0 |
| self.rel_pos_bins = rel_pos_bins |
| self.max_rel_pos = max_rel_pos |
| self.relative_attention_bias = nn.Embedding(self.rel_pos_bins, self.attention_heads) |
| seq_len = self.max_seq_len |
| context_position = torch.arange(seq_len, dtype=torch.long)[:, None] |
| memory_position = torch.arange(seq_len, dtype=torch.long)[None, :] |
| relative_position = memory_position - context_position |
| self.rp_bucket = relative_position_bucket( |
| relative_position, |
| num_buckets=self.rel_pos_bins, |
| max_distance=self.max_rel_pos |
| ) |
| self.rp_bucket -= self.rp_bucket.min() |
|
|
| def get_rel_pos_bias(self, x): |
| |
| if self.rp_bucket.device != x.device: |
| self.rp_bucket = self.rp_bucket.to(x.device) |
| seq_len = x.size(1) |
| rp_bucket = self.rp_bucket[:seq_len, :seq_len] |
| values = F.embedding(rp_bucket, self.relative_attention_bias.weight) |
| values = values.permute([2, 0, 1]) |
| return values.contiguous() |
|
|
| def forward( |
| self, |
| emb: torch.Tensor, |
| attn_mask: Optional[torch.Tensor] = None, |
| padding_mask: Optional[torch.Tensor] = None, |
| ) -> torch.Tensor: |
| |
| seq_len = emb.size(1) |
| x = self.emb_layer_norm(emb) |
| x = F.dropout(x, p=self.emb_dropout, training=self.training) |
|
|
| |
| if padding_mask is not None: |
| x = x * (1 - padding_mask.unsqueeze(-1).type_as(x)) |
|
|
| rel_pos_bias = self.get_rel_pos_bias(x).repeat(x.size(0), 1, 1) if self.rel_pos else None |
| if attn_mask is None: |
| attn_mask = rel_pos_bias |
| elif rel_pos_bias is not None: |
| attn_mask += rel_pos_bias |
|
|
| if attn_mask is not None and padding_mask is not None: |
| |
| attn_mask = attn_mask.view(x.size(0), -1, seq_len, seq_len) |
| attn_mask.masked_fill_( |
| padding_mask.unsqueeze(1).unsqueeze(2).to(torch.bool), |
| float("-inf") |
| ) |
| attn_mask = attn_mask.view(-1, seq_len, seq_len) |
| padding_mask = None |
| |
| for layer in self.layers: |
| x = layer(x, padding_mask=padding_mask, attn_bias=attn_mask) |
| |
| if self.final_layer_norm is not None: |
| x = self.final_layer_norm(x) |
|
|
| return x |