import torch import torch.nn as nn from transformers import AutoModel class HierarchicalClassifier(nn.Module): def __init__(self, base_model_name, num_labels=2, dropout_prob=0.1): super().__init__() self.encoder = AutoModel.from_pretrained(base_model_name) hidden_size = self.encoder.config.hidden_size self.hidden_size = hidden_size self.num_labels = num_labels self.chunk_attention = nn.Linear(hidden_size, 1) self.dropout = nn.Dropout(dropout_prob) self.classifier = nn.Linear(hidden_size, num_labels) def forward(self, input_ids, attention_mask, chunk_mask): B, K, L = input_ids.shape flat_input_ids = input_ids.view(B * K, L) flat_attention_mask = attention_mask.view(B * K, L) outputs = self.encoder( flat_input_ids, attention_mask=flat_attention_mask ) chunk_cls = outputs.last_hidden_state[:, 0, :] chunk_embeds = chunk_cls.view( B, K, self.hidden_size ) attn_scores = self.chunk_attention( chunk_embeds ).squeeze(-1) attn_scores = attn_scores.masked_fill( chunk_mask == 0, float("-inf") ) attn_weights = torch.softmax( attn_scores, dim=-1 ) doc_embed = ( chunk_embeds * attn_weights.unsqueeze(-1) ).sum(dim=1) doc_embed = self.dropout(doc_embed) logits = self.classifier(doc_embed) return logits