stratabert-tiny-ag-news-smoke / modeling_stratabert.py
dplotnikov's picture
Upload StrataBERT diagnostic checkpoint
c30089a verified
Raw
History Blame Contribute Delete
11.2 kB
"""HF-style StrataBERT model classes."""
from __future__ import annotations
import torch
from torch import nn
from .attention import StrataBertAttentionLayer
from .bidirectional_ssm import BidirectionalSSMLayer
from .configuration_stratabert import StrataBertConfig
from .heads import StrataBertClassificationHead, StrataBertLMHead, StrataBertRTDHead, StrataBertTokenClassificationHead
from .losses import masked_lm_loss, replaced_token_detection_loss, sequence_classification_loss, token_classification_loss
from .modeling_outputs import (
StrataBertMaskedLMOutput,
StrataBertModelOutput,
StrataBertPreTrainingOutput,
StrataBertSequenceClassifierOutput,
StrataBertTokenClassifierOutput,
)
from .padding import make_attention_mask, masked_hidden
from .pooling import StrataBertPooler
try:
from transformers import PreTrainedModel
except ModuleNotFoundError:
class PreTrainedModel(nn.Module): # type: ignore[no-redef]
config_class = None
def __init__(self, config):
super().__init__()
self.config = config
def post_init(self):
return None
class StrataBertPreTrainedModel(PreTrainedModel):
config_class = StrataBertConfig
base_model_prefix = "stratabert"
supports_gradient_checkpointing = True
def _init_weights(self, module):
if isinstance(module, nn.Linear):
nn.init.normal_(module.weight, mean=0.0, std=self.config.initializer_range)
if module.bias is not None:
nn.init.zeros_(module.bias)
elif isinstance(module, nn.Embedding):
nn.init.normal_(module.weight, mean=0.0, std=self.config.initializer_range)
if module.padding_idx is not None:
nn.init.zeros_(module.weight[module.padding_idx])
class StrataBertEmbeddings(nn.Module):
def __init__(self, config: StrataBertConfig):
super().__init__()
self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)
self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)
self.token_type_embeddings = nn.Embedding(config.type_vocab_size, config.hidden_size)
self.norm = nn.LayerNorm(config.hidden_size, eps=config.norm_eps)
self.dropout = nn.Dropout(config.hidden_dropout)
def forward(
self,
input_ids: torch.Tensor,
attention_mask: torch.Tensor,
token_type_ids: torch.Tensor | None = None,
position_ids: torch.Tensor | None = None,
) -> torch.Tensor:
batch, length = input_ids.shape
if position_ids is None:
position_ids = torch.arange(length, device=input_ids.device).unsqueeze(0).expand(batch, -1)
if token_type_ids is None:
token_type_ids = torch.zeros_like(input_ids)
x = (
self.word_embeddings(input_ids)
+ self.position_embeddings(position_ids)
+ self.token_type_embeddings(token_type_ids)
)
return masked_hidden(self.dropout(self.norm(x)), attention_mask)
class StrataBertEncoder(nn.Module):
def __init__(self, config: StrataBertConfig):
super().__init__()
layers = []
for layer_type in config.layer_types:
if layer_type == "ssm":
layers.append(BidirectionalSSMLayer(config))
else:
layers.append(StrataBertAttentionLayer(config, layer_type))
self.layers = nn.ModuleList(layers)
def forward(
self,
hidden_states: torch.Tensor,
attention_mask: torch.Tensor,
segment_ids: torch.Tensor | None = None,
output_hidden_states: bool = False,
) -> tuple[torch.Tensor, tuple[torch.Tensor, ...] | None]:
all_hidden = [] if output_hidden_states else None
for layer in self.layers:
if all_hidden is not None:
all_hidden.append(hidden_states)
if isinstance(layer, BidirectionalSSMLayer):
hidden_states = layer(hidden_states, attention_mask, segment_ids)
else:
hidden_states = layer(hidden_states, attention_mask, segment_ids)
if all_hidden is not None:
all_hidden.append(hidden_states)
return hidden_states, tuple(all_hidden) if all_hidden is not None else None
class StrataBertModel(StrataBertPreTrainedModel):
def __init__(self, config: StrataBertConfig):
super().__init__(config)
self.embeddings = StrataBertEmbeddings(config)
self.encoder = StrataBertEncoder(config)
self.pooler = StrataBertPooler(config.hidden_size, config.pooling_type)
self.post_init()
def forward(
self,
input_ids: torch.Tensor,
attention_mask: torch.Tensor | None = None,
token_type_ids: torch.Tensor | None = None,
position_ids: torch.Tensor | None = None,
segment_ids: torch.Tensor | None = None,
output_hidden_states: bool | None = None,
**kwargs,
) -> StrataBertModelOutput:
del kwargs
attention_mask = make_attention_mask(input_ids, attention_mask, self.config.pad_token_id)
output_hidden_states = self.config.output_hidden_states if output_hidden_states is None else output_hidden_states
hidden_states = self.embeddings(input_ids, attention_mask, token_type_ids, position_ids)
hidden_states, all_hidden = self.encoder(hidden_states, attention_mask, segment_ids, output_hidden_states)
pooled = self.pooler(hidden_states, attention_mask)
return StrataBertModelOutput(
last_hidden_state=hidden_states,
pooler_output=pooled,
hidden_states=all_hidden,
attentions=None,
ssm_states=None,
)
class StrataBertForSequenceClassification(StrataBertPreTrainedModel):
def __init__(self, config: StrataBertConfig):
super().__init__(config)
self.num_labels = config.num_labels
self.stratabert = StrataBertModel(config)
self.classifier = StrataBertClassificationHead(config)
self.post_init()
def forward(self, input_ids, attention_mask=None, token_type_ids=None, position_ids=None, segment_ids=None, labels=None, **kwargs):
outputs = self.stratabert(
input_ids=input_ids,
attention_mask=attention_mask,
token_type_ids=token_type_ids,
position_ids=position_ids,
segment_ids=segment_ids,
**kwargs,
)
logits = self.classifier(outputs.pooler_output)
loss = None
if labels is not None:
loss = sequence_classification_loss(logits, labels, self.num_labels, self.config.problem_type)
return StrataBertSequenceClassifierOutput(loss=loss, logits=logits, hidden_states=outputs.hidden_states)
class StrataBertForTokenClassification(StrataBertPreTrainedModel):
def __init__(self, config: StrataBertConfig):
super().__init__(config)
self.num_labels = config.num_labels
self.stratabert = StrataBertModel(config)
self.classifier = StrataBertTokenClassificationHead(config)
self.post_init()
def forward(self, input_ids, attention_mask=None, token_type_ids=None, position_ids=None, segment_ids=None, labels=None, **kwargs):
outputs = self.stratabert(
input_ids=input_ids,
attention_mask=attention_mask,
token_type_ids=token_type_ids,
position_ids=position_ids,
segment_ids=segment_ids,
**kwargs,
)
logits = self.classifier(outputs.last_hidden_state)
loss = None
if labels is not None:
mask = make_attention_mask(input_ids, attention_mask, self.config.pad_token_id)
loss = token_classification_loss(logits, labels, mask, self.num_labels)
return StrataBertTokenClassifierOutput(loss=loss, logits=logits, hidden_states=outputs.hidden_states)
class StrataBertForMaskedLM(StrataBertPreTrainedModel):
_tied_weights_keys = {
"lm_head.decoder.weight": "stratabert.embeddings.word_embeddings.weight",
"lm_head.decoder.bias": "lm_head.bias",
}
def __init__(self, config: StrataBertConfig):
super().__init__(config)
self.stratabert = StrataBertModel(config)
self.lm_head = StrataBertLMHead(config, self.stratabert.embeddings.word_embeddings.weight)
self.post_init()
def forward(self, input_ids, attention_mask=None, token_type_ids=None, position_ids=None, segment_ids=None, labels=None, **kwargs):
outputs = self.stratabert(
input_ids=input_ids,
attention_mask=attention_mask,
token_type_ids=token_type_ids,
position_ids=position_ids,
segment_ids=segment_ids,
**kwargs,
)
logits = self.lm_head(outputs.last_hidden_state)
loss = masked_lm_loss(logits, labels) if labels is not None else None
return StrataBertMaskedLMOutput(loss=loss, logits=logits, hidden_states=outputs.hidden_states)
class StrataBertForPreTraining(StrataBertPreTrainedModel):
_tied_weights_keys = {
"lm_head.decoder.weight": "stratabert.embeddings.word_embeddings.weight",
"lm_head.decoder.bias": "lm_head.bias",
}
def __init__(self, config: StrataBertConfig):
super().__init__(config)
self.stratabert = StrataBertModel(config)
self.lm_head = StrataBertLMHead(config, self.stratabert.embeddings.word_embeddings.weight)
self.rtd_head = StrataBertRTDHead(config)
self.post_init()
def forward(
self,
input_ids,
attention_mask=None,
token_type_ids=None,
position_ids=None,
segment_ids=None,
labels=None,
rtd_labels=None,
mlm_weight: float = 1.0,
rtd_weight: float = 0.25,
**kwargs,
):
outputs = self.stratabert(
input_ids=input_ids,
attention_mask=attention_mask,
token_type_ids=token_type_ids,
position_ids=position_ids,
segment_ids=segment_ids,
**kwargs,
)
prediction_logits = self.lm_head(outputs.last_hidden_state)
rtd_logits = self.rtd_head(outputs.last_hidden_state)
mlm = masked_lm_loss(prediction_logits, labels) if labels is not None else None
rtd = None
if rtd_labels is not None:
mask = make_attention_mask(input_ids, attention_mask, self.config.pad_token_id)
rtd = replaced_token_detection_loss(rtd_logits, rtd_labels, mask)
loss = None
if mlm is not None and rtd is not None:
loss = mlm_weight * mlm + rtd_weight * rtd
elif mlm is not None:
loss = mlm
elif rtd is not None:
loss = rtd
return StrataBertPreTrainingOutput(
loss=loss,
prediction_logits=prediction_logits,
rtd_logits=rtd_logits,
mlm_loss=mlm,
rtd_loss=rtd,
hidden_states=outputs.hidden_states,
)