Download scandl_module/original_scandl/sp_transformer_model.py from DiLi-Lab/ScanDL2: direct link, hf CLI and curl.
- Browser
- Download file 6.08 kB
-
https://huggingface.co/DiLi-Lab/ScanDL2/resolve/main/scandl_module/original_scandl/sp_transformer_model.py
- Command line
-
hf download hf://DiLi-Lab/ScanDL2/scandl_module/original_scandl/sp_transformer_model.py
-
curl -L -o sp_transformer_model.py https://huggingface.co/DiLi-Lab/ScanDL2/resolve/main/scandl_module/original_scandl/sp_transformer_model.py
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 | |