| import torch |
| import torch.nn as nn |
| from transformers import AutoConfig, AutoModel, PreTrainedModel |
| from transformers.modeling_outputs import SequenceClassifierOutput |
| from .configuration_baseline_enc import BaselineEncConfig |
|
|
| class Encoder(nn.Module): |
| def __init__(self, name, pooling="cls"): |
| super().__init__() |
| base_cfg = AutoConfig.from_pretrained(name) |
| self.backbone = AutoModel.from_config(base_cfg) |
| self.pooling = pooling |
| self.hidden_dim = self.backbone.config.hidden_size |
|
|
| def forward(self, ids, mask): |
| hidden = self.backbone(input_ids=ids, attention_mask=mask).last_hidden_state |
| if self.pooling == "cls": |
| return hidden[:, 0, :] |
| m = mask.unsqueeze(-1).float() |
| return (hidden * m).sum(1) / m.sum(1).clamp(min=1e-9) |
|
|
| class SarcasmHead(nn.Module): |
| def __init__(self, in_dim, hidden_dim, dropout=0.1): |
| super().__init__() |
| self.mlp = nn.Sequential( |
| nn.Linear(in_dim, hidden_dim), |
| nn.ReLU(), |
| nn.Dropout(dropout), |
| nn.Linear(hidden_dim, 1), |
| ) |
|
|
| def forward(self, hidden): |
| return self.mlp(hidden).squeeze(-1) |
|
|
| class BaselineEncForSequenceClassification(PreTrainedModel): |
| config_class = BaselineEncConfig |
| base_model_prefix = "baseline_enc" |
|
|
| def __init__(self, config): |
| super().__init__(config) |
| self.encoder = Encoder(config.encoder_name, config.pooling) |
| self.head = SarcasmHead( |
| self.encoder.hidden_dim, |
| config.mlp_hidden, |
| config.dropout, |
| ) |
| self.post_init() |
|
|
| def forward(self, input_ids=None, attention_mask=None, labels=None, **kwargs): |
| pooled = self.encoder(input_ids, attention_mask) |
| binary_logit = self.head(pooled) |
| logits = torch.stack([-binary_logit, binary_logit], dim=-1) |
|
|
| loss = None |
| if labels is not None: |
| loss = nn.CrossEntropyLoss()(logits, labels) |
|
|
| return SequenceClassifierOutput(loss=loss, logits=logits) |
|
|