Download T5_encoder.py from ggomarobot/KSSDS: direct link, hf CLI and curl.
- Browser
- Download file 6.55 kB
-
https://huggingface.co/ggomarobot/KSSDS/resolve/main/T5_encoder.py
- Command line
-
hf download hf://ggomarobot/KSSDS/T5_encoder.py
-
curl -L -o T5_encoder.py https://huggingface.co/ggomarobot/KSSDS/resolve/main/T5_encoder.py
6.55 kB
| import copy | |
| from typing import Optional, Tuple, Union | |
| import torch | |
| from torch import nn | |
| from torch.utils import checkpoint | |
| from transformers.models.t5.modeling_t5 import ( | |
| T5PreTrainedModel, | |
| T5Config, | |
| T5Stack, | |
| T5_START_DOCSTRING, | |
| T5_ENCODER_INPUTS_DOCSTRING, | |
| PARALLELIZE_DOCSTRING, | |
| DEPARALLELIZE_DOCSTRING, | |
| _CONFIG_FOR_DOC | |
| ) | |
| from transformers.modeling_outputs import TokenClassifierOutput | |
| from transformers.utils import ( | |
| add_start_docstrings, | |
| add_start_docstrings_to_model_forward, | |
| replace_return_docstrings | |
| ) | |
| from transformers.utils.model_parallel_utils import assert_device_map, get_device_map | |
| from transformers.utils.logging import get_logger | |
| logger = get_logger("transformers") | |
| class T5ForTokenClassification(T5PreTrainedModel): | |
| _keys_to_ignore_on_load_missing = [r"encoder.embed_tokens.weight"] | |
| def __init__(self, config: T5Config, num_labels: int = None): | |
| super().__init__(config) | |
| self.model_dim = config.d_model | |
| self.shared = nn.Embedding(config.vocab_size, config.d_model) | |
| encoder_config = copy.deepcopy(config) | |
| encoder_config.is_decoder = False | |
| encoder_config.is_encoder_decoder = False | |
| encoder_config.use_cache = False | |
| self.encoder = T5Stack(encoder_config, self.shared) | |
| classifier_dropout = ( | |
| config.classifier_dropout if hasattr(config, 'classifier_dropout') else config.dropout_rate | |
| ) | |
| self.dropout = nn.Dropout(classifier_dropout) | |
| # Use custom num_labels if provided, otherwise use config.num_labels | |
| self.num_labels = num_labels if num_labels is not None else config.num_labels | |
| self.classifier = nn.Linear(config.d_model, self.num_labels) | |
| # Initialize weights and apply final processing | |
| self.post_init() | |
| # Model parallel | |
| self.model_parallel = False | |
| self.device_map = None | |
| def parallelize(self, device_map=None): | |
| self.device_map = ( | |
| get_device_map(len(self.encoder.block), range(torch.cuda.device_count())) | |
| if device_map is None | |
| else device_map | |
| ) | |
| assert_device_map(self.device_map, len(self.encoder.block)) | |
| self.encoder.parallelize(self.device_map) | |
| self.classifier.to(self.encoder.first_device) | |
| self.model_parallel = True | |
| def deparallelize(self): | |
| self.encoder.deparallelize() | |
| self.encoder = self.encoder.to("cpu") | |
| self.classifier = self.classifier.to("cpu") | |
| self.model_parallel = False | |
| self.device_map = None | |
| torch.cuda.empty_cache() | |
| def get_input_embeddings(self): | |
| return self.shared | |
| def set_input_embeddings(self, new_embeddings): | |
| self.shared = new_embeddings | |
| self.encoder.set_input_embeddings(new_embeddings) | |
| def get_encoder(self): | |
| return self.encoder | |
| def _prune_heads(self, heads_to_prune): | |
| """ | |
| Prunes heads of the model. heads_to_prune: dict of {layer_num: list of heads to prune in this layer} See base | |
| class PreTrainedModel | |
| """ | |
| for layer, heads in heads_to_prune.items(): | |
| self.encoder.block[layer].layer[0].SelfAttention.prune_heads(heads) | |
| def check_for_nans(self, tensor, name="Tensor"): | |
| if torch.isnan(tensor).any(): | |
| print(f"NaNs detected in {name}: {tensor}") | |
| def forward( | |
| self, | |
| input_ids: Optional[torch.LongTensor] = None, | |
| attention_mask: Optional[torch.FloatTensor] = None, | |
| head_mask: Optional[torch.FloatTensor] = None, | |
| inputs_embeds: Optional[torch.FloatTensor] = None, | |
| labels: Optional[torch.LongTensor] = None, | |
| output_attentions: Optional[bool] = None, | |
| output_hidden_states: Optional[bool] = None, | |
| return_dict: Optional[bool] = None, | |
| ) -> Union[Tuple[torch.FloatTensor], TokenClassifierOutput]: | |
| r""" | |
| labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*): | |
| Labels for computing the token classification loss. Indices should be in `[0, ..., config.num_labels - 1]`. | |
| Returns: | |
| """ | |
| return_dict = return_dict if return_dict is not None else self.config.use_return_dict | |
| outputs = self.encoder( | |
| input_ids=input_ids, | |
| attention_mask=attention_mask, | |
| inputs_embeds=inputs_embeds, | |
| head_mask=head_mask, | |
| output_attentions=output_attentions, | |
| output_hidden_states=output_hidden_states, | |
| return_dict=return_dict, | |
| ) | |
| # Check encoder outputs for NaNs | |
| # self.check_for_nans(outputs[0], name="Encoder Output") | |
| # outputs[0]: last_hidden_state | |
| sequence_output = outputs[0] | |
| sequence_output = self.dropout(sequence_output) | |
| ''' | |
| # Check after dropout | |
| self.check_for_nans(sequence_output, name="After Dropout") | |
| # Check for NaNs or Infs in classifier parameters | |
| for name, param in self.classifier.named_parameters(): | |
| if torch.isnan(param).any(): | |
| print(f"NaNs detected in classifier parameter: {name}") | |
| if torch.isinf(param).any(): | |
| print(f"Infs detected in classifier parameter: {name}") | |
| ''' | |
| logits = self.classifier(sequence_output) | |
| # Check logits for NaNs | |
| # self.check_for_nans(logits, name="Logits") | |
| loss = None | |
| if labels is not None: | |
| ignore_index = -1 | |
| loss_fct = nn.CrossEntropyLoss(ignore_index=ignore_index) | |
| loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1)) | |
| if not return_dict: | |
| output = (logits,) + outputs[2:] | |
| return ((loss,) + output) if loss is not None else output | |
| return TokenClassifierOutput( | |
| loss=loss, | |
| logits=logits, | |
| hidden_states=outputs.hidden_states, | |
| attentions=outputs.attentions | |
| ) |