import torch
from transformers import BertModel, BertTokenizer
class BertBiLstmCrfNER(torch.nn.Module):
def __init__(self, bert_dir, num_tags, lstm_hidden=256, lstm_layers=2):
super().__init__()
self.bert_encoder = BertModel.from_pretrained(bert_dir)
self.bilstm_layer = torch.nn.LSTM(
input_size=768, hidden_size=lstm_hidden,
num_layers=lstm_layers, bidirectional=True, batch_first=True
)
self.hidden_to_tag = torch.nn.Linear(lstm_hidden * 2, num_tags)
# ......省略了CRF层的初始化代码
# 核心逻辑:CRF层包含转移矩阵transition_scores,维度为(num_tags, num_tags)
# 前向计算使用Viterbi算法解码最优标签路径
def forward(self, input_ids, attention_mask, label_ids=None):
bert_out = self.bert_encoder(input_ids=input_ids, attention_mask=attention_mask)
lstm_out, _ = self.bilstm_layer(bert_out.last_hidden_state)
emit_scores = self.hidden_to_tag(lstm_out)
# ......省略了CRF前向算法和Viterbi解码代码
# 核心逻辑:训练时计算CRF的log_likelihood损失
# 预测时使用Viterbi解码返回最优标签序列