ScanDL2 / scandl_module /original_scandl /sp_transformer_model.py
Di0nigi's picture
First commit
95456ed verified
Raw History Blame Contribute Delete
6.08 kB
from transformers import AutoConfig
from transformers.models.bert.modeling_bert import BertEncoder, BertModel
import torch
import torch as th
import torch.nn as nn
from typing import Optional
from .utils.nn import (
SiLU,
linear,
timestep_embedding,
)
class TransformerNetModel(nn.Module):
"""
The ScanDL transformer.
"""
def __init__(
self,
input_dims,
output_dims,
hidden_t_dim,
num_transformer_layers,
num_transformer_heads,
one_noise_step,
mask_padding,
dropout=0,
config=None,
config_name="bert-base-uncased",
vocab_size=None,
init_pretrained="no",
logits_mode=1,
):
super().__init__()
if config is None:
config = AutoConfig.from_pretrained(config_name)
config.hidden_dropout_prob = dropout
config.num_hidden_layers = num_transformer_layers
config.num_attention_heads = num_transformer_heads
config.hidden_size = input_dims
self.input_dims = input_dims
self.hidden_t_dim = hidden_t_dim
self.output_dims = output_dims
self.dropout = dropout
self.logits_mode = logits_mode
self.mask_padding = mask_padding
self.one_noise_step = one_noise_step
self.bert_for_embedding = BertModel.from_pretrained(config_name)
# freeze BERT parameters (so that embeddings are freezed)
for param in self.bert_for_embedding.parameters():
param.requires_grad = False
self.sn_sp_repr_embedding = nn.Embedding(self.hidden_t_dim, self.input_dims)
self.positional_encoding = nn.Embedding(self.hidden_t_dim, self.input_dims)
self.sn_input_ids_embedding = self.bert_for_embedding.embeddings.word_embeddings
# additional linear layer needed if hidden is not 768 to map from pretrained BERT embeddings to other dim
if self.input_dims != 768:
self.proj_bert_emb = nn.Linear(768, self.input_dims)
self.lm_head = nn.Linear(self.input_dims, self.hidden_t_dim)
with torch.no_grad():
self.lm_head.weight = self.sn_sp_repr_embedding.weight
time_embed_dim = hidden_t_dim * 4
self.time_embed = nn.Sequential(
linear(hidden_t_dim, time_embed_dim),
SiLU(),
linear(time_embed_dim, config.hidden_size),
)
self.input_transformers = BertEncoder(config)
self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
self.dropout = nn.Dropout(config.hidden_dropout_prob)
def get_embeds(
self,
sn_sp_repr,
sn_input_ids,
indices_pos_enc,
):
sn_sp_emb = self.sn_sp_repr_embedding(sn_sp_repr)
pos_enc = self.positional_encoding(indices_pos_enc)
if self.input_dims == 768:
sn_input_ids_emb = self.sn_input_ids_embedding(sn_input_ids)
else:
sn_input_ids_emb_bert_embs = self.sn_input_ids_embedding(sn_input_ids)
sn_input_ids_emb = self.proj_bert_emb(sn_input_ids_emb_bert_embs)
return sn_sp_emb, pos_enc, sn_input_ids_emb
def get_logits(self, model_output):
if self.logits_mode == 1:
return self.lm_head(model_output)
elif self.logits_mode == 2: # standard cosine similarity
raise NotImplementedError(
"standard cosine similarity not yet implemented for sp model output."
)
else:
raise NotImplementedError
def forward(
self,
x, # x_t
ts,
sn_input_ids_emb,
pos_enc,
attention_mask: Optional[torch.tensor] = None,
atten_vis: Optional[bool] = False,
):
"""
Apply the model to an input batch.
:param x: the noised input ID embeddings
:param ts: a 1-D batch of timesteps.
:param sn_input_ids_emb: the BERT embeddings
:param pos_enc: the positional embeddings
:param attention_mask: the attention mask (only given during training, not during inference)
:atten_vis: visualise attention
"""
# timestep embedding
emb_t = self.time_embed(timestep_embedding(ts, self.hidden_t_dim))
# add the input x_t, the positional encoding pos_enc, the word ID embedding word_id_emb, and the timestep emb
emb_inputs = x + pos_enc + sn_input_ids_emb + emb_t.unsqueeze(1).expand(-1, x.size(1), -1)
# pipe through dropout and layer normalisation
emb_inputs = self.dropout(self.LayerNorm(emb_inputs))
if self.mask_padding:
if attention_mask == None:
raise ValueError("padding should be masked, but no attention mask given.")
extended_attention_mask = attention_mask[:, None, None, :]
if atten_vis:
model_out = self.input_transformers(
emb_inputs, attention_mask=extended_attention_mask, output_attentions=True
)
input_trans_hidden_states = model_out.last_hidden_state
attention_scores = model_out.attentions
else:
input_trans_hidden_states = self.input_transformers(
emb_inputs, attention_mask=extended_attention_mask
).last_hidden_state
else:
if atten_vis:
model_out = self.input_transformers(emb_inputs, output_attentions=True)
input_trans_hidden_states = model_out.last_hidden_state
attention_scores = model_out.attentions
else:
input_trans_hidden_states = self.input_transformers(emb_inputs).last_hidden_state
h = input_trans_hidden_states
h = h.type(x.dtype)
if atten_vis:
return h, attention_scores
else:
return h