import math, torch import torch.nn as nn import torch.nn.functional as F from transformers import PreTrainedModel from transformers.modeling_outputs import MaskedLMOutput, CausalLMOutputWithCrossAttentions from .configuration_gpt_bert import GPTBertConfig class GeGLU(nn.Module): def forward(self, x): x, gate = x.chunk(2, dim=-1) return x * F.gelu(gate, approximate='tanh') class FeedForward(nn.Module): def __init__(self, config): super().__init__() self.mlp = nn.Sequential( nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps, elementwise_affine=False) ,nn.Linear(config.hidden_size, 2*config.intermediate_size, bias=False) ,GeGLU() ,nn.LayerNorm(config.intermediate_size, eps=config.layer_norm_eps, elementwise_affine=False) ,nn.Linear(config.intermediate_size, config.hidden_size, bias=False) ,nn.Dropout(config.hidden_dropout_prob) ) self._init(config.hidden_size) def _init(self, h): std = math.sqrt(2.0 / (5.0 * h)) nn.init.trunc_normal_(self.mlp[1].weight, mean=0.0, std=std, a=-2*std, b=2*std) nn.init.trunc_normal_(self.mlp[-2].weight, mean=0.0, std=std, a=-2*std, b=2*std) def forward(self, x): return self.mlp(x) class Attention(nn.Module): def __init__(self, config): super().__init__() if config.hidden_size % config.num_attention_heads != 0: raise ValueError('hidden not divisible by heads') self.nh = config.num_attention_heads self.dh = config.hidden_size // config.num_attention_heads self.qkv = nn.Linear(config.hidden_size, 3*config.hidden_size, bias=False) self.o = nn.Linear(config.hidden_size, config.hidden_size, bias=False) self.drop = nn.Dropout(config.hidden_dropout_prob) def forward(self, x, attn_mask, rel): B,S,H = x.shape qkv = self.qkv(x).view(B,S,3,self.nh,self.dh).permute(2,0,3,1,4) q,k,v = qkv[0],qkv[1],qkv[2] attn = (q @ k.transpose(-1,-2)) / math.sqrt(self.dh) if attn_mask is not None: attn = attn.masked_fill(attn_mask[:,None,:, :]==0, float('-inf')) attn = torch.softmax(attn, dim=-1) attn = self.drop(attn) y = attn @ v y = y.transpose(1,2).contiguous().view(B,S,H) return self.o(y) class Block(nn.Module): def __init__(self, config): super().__init__() self.attn = Attention(config) self.ff = FeedForward(config) def forward(self, x, attn_mask, rel): x = x + self.attn(x, attn_mask, rel) x = x + self.ff(x) return x class Encoder(nn.Module): def __init__(self, config): super().__init__() self.layers = nn.ModuleList([Block(config) for _ in range(config.num_hidden_layers)]) def forward(self, x, attn_mask, rel): for layer in self.layers: x = layer(x, attn_mask, rel) return x class Embedding(nn.Module): def __init__(self, config): super().__init__() self.word_embedding = nn.Embedding(config.vocab_size, config.hidden_size) self.pos_embedding = nn.Embedding(config.max_position_embeddings, config.hidden_size) self.dropout = nn.Dropout(config.hidden_dropout_prob) def forward(self, input_ids): B,S = input_ids.shape pos = torch.arange(0,S, device=input_ids.device).unsqueeze(0).expand(B,S) x = self.word_embedding(input_ids) + self.pos_embedding(pos) return self.dropout(x), None class CoreModel(nn.Module): def __init__(self, config): super().__init__() self.embedding = Embedding(config) self.transformer = Encoder(config) self.layer_norm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps, elementwise_affine=False) self.head = nn.Linear(config.hidden_size, config.vocab_size, bias=False) self.head.weight = self.embedding.word_embedding.weight def forward(self, input_ids, attention_mask=None): x,_ = self.embedding(input_ids) if attention_mask is not None: attn = attention_mask.unsqueeze(1) else: attn = None x = self.transformer(x, attn, None) x = self.layer_norm(x) return self.head(x) class GPTBertForMaskedLM(PreTrainedModel): config_class = GPTBertConfig base_model_prefix = 'gpt_bert' def __init__(self, config: GPTBertConfig): super().__init__(config) self.model = CoreModel(config) def forward(self, input_ids, attention_mask=None, labels=None): logits = self.model(input_ids, attention_mask) loss=None if labels is not None: loss_fct = nn.CrossEntropyLoss(ignore_index=-100) loss = loss_fct(logits.view(-1, logits.size(-1)), labels.view(-1)) return MaskedLMOutput(loss=loss, logits=logits) class GPTBertForCausalLM(PreTrainedModel): config_class = GPTBertConfig base_model_prefix = 'gpt_bert' def __init__(self, config: GPTBertConfig): super().__init__(config) self.model = CoreModel(config) def prepare_inputs_for_generation(self, input_ids, **kwargs): return {'input_ids': input_ids} def forward(self, input_ids, attention_mask=None, labels=None): logits = self.model(input_ids, attention_mask) loss=None if labels is not None: shift_logits = logits[..., :-1, :].contiguous() shift_labels = labels[..., 1:].contiguous() loss_fct = nn.CrossEntropyLoss(ignore_index=-100) loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)) return CausalLMOutputWithCrossAttentions(loss=loss, logits=logits)