|
|
| import torch |
| import torch.nn as nn |
| from transformers import PretrainedConfig, PreTrainedModel |
| from transformers.modeling_outputs import SequenceClassifierOutput |
|
|
|
|
| class MyTextConfig(PretrainedConfig): |
| model_type = "my-text-sequence-classification" |
|
|
| def __init__( |
| self, |
| vocab_size=30522, |
| max_position_embeddings=128, |
| hidden_size=128, |
| num_labels=2, |
| hidden_dropout_prob=0.1, |
| **kwargs |
| ): |
| super().__init__(**kwargs) |
|
|
| |
| |
| self.vocab_size = vocab_size |
|
|
| |
| |
| self.max_position_embeddings = max_position_embeddings |
|
|
| |
| |
| self.hidden_size = hidden_size |
|
|
| |
| |
| self.num_labels = num_labels |
|
|
| |
| |
| self.hidden_dropout_prob = hidden_dropout_prob |
|
|
|
|
| class MyTextSequenceClassification(PreTrainedModel): |
| config_class = MyTextConfig |
|
|
| def __init__(self, config): |
| super().__init__(config) |
|
|
| |
| |
| self.token_embedding = nn.Embedding( |
| config.vocab_size, |
| config.hidden_size |
| ) |
|
|
| |
| |
| self.position_embedding = nn.Embedding( |
| config.max_position_embeddings, |
| config.hidden_size |
| ) |
|
|
| |
| |
| self.dropout = nn.Dropout(config.hidden_dropout_prob) |
|
|
| |
| |
| self.classifier = nn.Linear( |
| config.hidden_size, |
| config.num_labels |
| ) |
|
|
| |
| |
| self.loss_fn = nn.CrossEntropyLoss() |
|
|
| self.post_init() |
|
|
| def forward(self, input_ids, attention_mask=None, labels=None): |
| batch_size, seq_length = input_ids.size() |
|
|
| |
| |
| position_ids = torch.arange( |
| seq_length, |
| dtype=torch.long, |
| device=input_ids.device |
| ).unsqueeze(0).expand(batch_size, seq_length) |
|
|
| |
| |
| x = self.token_embedding(input_ids) + self.position_embedding(position_ids) |
|
|
| |
| |
| if attention_mask is not None: |
| mask = attention_mask.unsqueeze(-1).float() |
| x = x * mask |
| pooled_output = x.sum(dim=1) / mask.sum(dim=1).clamp(min=1.0) |
| else: |
| pooled_output = x.mean(dim=1) |
|
|
| pooled_output = self.dropout(pooled_output) |
|
|
| |
| |
| logits = self.classifier(pooled_output) |
|
|
| |
| |
| loss = None |
| if labels is not None: |
| loss = self.loss_fn(logits, labels) |
|
|
| return SequenceClassifierOutput( |
| loss=loss, |
| logits=logits |
| ) |
|
|
|
|
| if __name__ == "__main__": |
| config = MyTextConfig() |
| model = MyTextSequenceClassification(config) |
|
|
| input_ids = torch.randint(0, config.vocab_size, (2, 10)) |
| attention_mask = torch.ones_like(input_ids) |
| labels = torch.tensor([0, 1]) |
|
|
| outputs = model( |
| input_ids=input_ids, |
| attention_mask=attention_mask, |
| labels=labels |
| ) |
|
|
| print("Loss:", outputs.loss) |
| print("Logits:", outputs.logits) |
| print("Logits shape:", outputs.logits.shape) |
|
|