自定义Huggingface BERT二分类模型准确率报错及模型调用咨询
BERT二分类情感识别问题解决方案
问题1:准确率计算报错修复及代码优化
报错原因
你使用的CrossEntropyLoss对应输出维度为[batch_size, 2]的二维张量,而targets是一维的0/1标签,原有代码直接对二维输出做>=0.5判断,得到二维布尔数组,和一维标签维度不匹配,因此触发格式不兼容错误。
修复方案
将验证环节的
outputs = np.array(outputs) >= 0.5
修改为
outputs = np.argmax(np.array(outputs), axis=1)
直接取每个样本概率最高的类别索引,得到一维的0/1预测结果,和targets维度一致即可正常计算准确率。
代码优化点
- 模型保存代码存在错误,
torch.save(model.state_dict, 'model.pt')中state_dict是方法,需加括号调用才能保存权重,修改为torch.save(model.state_dict(), 'model.pt'),否则后续加载会报错 - 训练函数中重复调用了
optimizer.zero_grad(),前向传播和反向传播前各调用了一次,删掉其中一次即可 - 读取数据时未使用上下文管理器,建议将
open('test.txt', 'r')改为with open('test.txt','r',encoding='utf-8') as file1:,避免文件句柄泄漏 - BERT微调的学习率1e-4过高,建议调整为3e-5~5e-5区间,避免破坏预训练权重的语义特征
- 验证环节不需要过
sigmoid激活,CrossEntropyLoss自带softmax归一化,直接取argmax即可 - 模型forward函数中定义了
hidden变量但未使用,属于冗余代码,要么删除该行,要么将hidden传入线性层输出,避免逻辑混乱 - 可增加学习率衰减策略(如线性warmup后衰减)、打印精确率/召回率/F1等多维度评估指标,提升模型效果和可解释性
问题2:模型加载与实时推理实现
首先保证新的py文件中复用训练时完全一致的模型结构、分词器、超参数,参考代码如下:
import numpy as np import torch from transformers import BertTokenizer, BertModel from torch import nn from torch import cuda # 与训练阶段完全一致的超参数 device = 'cuda' if cuda.is_available() else 'cpu' MAX_LEN = 200 tokenizer = BertTokenizer.from_pretrained('bert-base-multilingual-uncased') # 与训练阶段完全一致的模型结构 class BERTClass(torch.nn.Module): def __init__(self): super(BERTClass, self).__init__() self.bert = BertModel.from_pretrained('bert-base-multilingual-uncased',return_dict=False,num_labels = 2) self.lstm = nn.LSTM(768, 256, batch_first=True, bidirectional=True) self.linear = nn.Linear(256*2,2) def forward(self, ids , mask): sequence_output, pooled_output = self.bert(ids, attention_mask=mask ) lstm_output, (h, c) = self.lstm(sequence_output) linear_output = self.linear(lstm_output[:, -1].view(-1, 256 * 2)) return linear_output # 加载预训练权重 model = BERTClass() model.load_state_dict(torch.load('model.pt', map_location=device)) model.to(device) model.eval() # 单样本推理函数 def predict_sentiment(text): text = " ".join(text.split()) inputs = tokenizer.encode_plus( text, None, add_special_tokens=True, max_length=MAX_LEN, pad_to_max_length=True, return_token_type_ids=False, truncation=True ) ids = torch.tensor([inputs['input_ids']], dtype=torch.long).to(device) mask = torch.tensor([inputs['attention_mask']], dtype=torch.long).to(device) with torch.no_grad(): outputs = model(ids, mask) pred = np.argmax(outputs.cpu().numpy(), axis=1)[0] return "positive(正面)" if pred == 1 else "negative(负面)" # 实时交互分类 if __name__ == "__main__": print("输入q即可退出程序") while True: input_text = input("请输入要分类的句子:") if input_text.strip() == 'q': break res = predict_sentiment(input_text) print(f"分类结果:{res}\n")
内容的提问来源于stack exchange,提问作者Qs13
相关产品推荐
相关产品推荐

