如何用yangheng/deberta-v3-base-absa-v1.1模型实现ABSA任务并修复报错?
问题描述
现有一个包含文本和预定义Aspect的DataFrame,部分行无预定义Aspect,数据示例如下:
data = { 'text': [ "The camera quality of this phone is amazing.", "The belt is poor quality", "The battery life could be improved.", "The display is sharp and vibrant.", "The customer service was disappointing." ], 'aspects': [ ["camera", "phone"], [], ["battery", "life"], ["display"], ["customer service"] ] } df = pd.DataFrame(data)
需完成两项任务:
- 基于文本的预定义Aspect生成情感得分;
- 对无预定义Aspect的行,自动提取Aspect并生成对应情感得分。
使用模型yangheng/deberta-v3-base-absa-v1.1,尝试编写代码后报错,原代码如下:
import torch from transformers import AutoTokenizer, AutoModelForSequenceClassification import pandas as pd # Load the ABSA model and tokenizer model_name = "yangheng/deberta-v3-base-absa-v1.1" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForSequenceClassification.from_pretrained(model_name) # Generate aspects and sentiments aspects = [] sentiments = [] for index, row in df.iterrows(): text = row['text'] row_aspects = row['aspects'] aspect_sentiments = [] for aspect in row_aspects: inputs = tokenizer(text, aspect, return_tensors="pt") with torch.inference_mode(): outputs = model(**inputs) predicted_sentiment = torch.argmax(outputs.logits).item() sentiment_label = model.config.id2label[predicted_sentiment] aspect_sentiments.append(f"{aspect}: {sentiment_label}") aspects.append(row_aspects) sentiments.append(aspect_sentiments) # Add the generated aspects and sentiments to the DataFrame df['generated_aspects'] = aspects df['generated_sentiments'] = sentiments # Print the updated DataFrame print(df)
模型官方使用示例:
import torch import torch.nn.functional as F from transformers import AutoTokenizer, AutoModelForSequenceClassification model_name = "yangheng/deberta-v3-base-absa-v1.1" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForSequenceClassification.from_pretrained(model_name) aspects = ["food", "service"] text = "The food was great but the service was terrible." sentiment_aspect = {} for aspect in aspects: inputs = tokenizer(text, aspect, return_tensors="pt") with torch.inference_mode(): outputs = model(**inputs) scores = F.softmax(outputs.logits[0], dim=-1) label_id = torch.argmax(scores).item() sentiment_aspect[aspect] = (model.config.id2label[label_id], scores[label_id].item()) print(sentiment_aspect)
期望输出:DataFrame新增generated_aspects和generated_sentiments列,无预定义Aspect的行自动提取Aspect并生成对应情感得分。
解决方案
问题分析
原代码仅处理了有预定义Aspect的行,未实现无预定义Aspect时的自动提取功能;同时未计算情感得分(仅输出标签),也未处理长文本截断等潜在格式问题。
完整实现代码
要完成自动提取Aspect,需搭配Aspect提取模型(yangheng/deberta-v3-base-aspect-extractor),先提取文本中的Aspect,再用ABSA模型判断情感。以下是完整代码:
import torch import torch.nn.functional as F from transformers import AutoTokenizer, AutoModelForSequenceClassification, AutoModelForTokenClassification import pandas as pd from typing import List # 加载ABSA情感分析模型和Aspect提取模型 absa_model_name = "yangheng/deberta-v3-base-absa-v1.1" aspect_extractor_model_name = "yangheng/deberta-v3-base-aspect-extractor" # 初始化ABSA模型和分词器 absa_tokenizer = AutoTokenizer.from_pretrained(absa_model_name) absa_model = AutoModelForSequenceClassification.from_pretrained(absa_model_name) # 初始化Aspect提取模型和分词器 aspect_extractor_tokenizer = AutoTokenizer.from_pretrained(aspect_extractor_model_name) aspect_extractor_model = AutoModelForTokenClassification.from_pretrained(aspect_extractor_model_name) def extract_aspects(text: str) -> List[str]: """从文本中自动提取Aspect""" inputs = aspect_extractor_tokenizer(text, return_tensors="pt", truncation=True, max_length=512) with torch.inference_mode(): outputs = aspect_extractor_model(**inputs) predictions = torch.argmax(outputs.logits, dim=2)[0].tolist() tokens = aspect_extractor_tokenizer.convert_ids_to_tokens(inputs["input_ids"][0]) aspects = [] current_aspect = [] for token, pred in zip(tokens, predictions): if pred == 1: # B-ASPECT(Aspect起始标记) if current_aspect: aspects.append(aspect_extractor_tokenizer.convert_tokens_to_string(current_aspect)) current_aspect = [] current_aspect.append(token) elif pred == 2: # I-ASPECT(Aspect延续标记) current_aspect.append(token) else: if current_aspect: aspects.append(aspect_extractor_tokenizer.convert_tokens_to_string(current_aspect)) current_aspect = [] # 处理最后一个未闭合的Aspect if current_aspect: aspects.append(aspect_extractor_tokenizer.convert_tokens_to_string(current_aspect)) # 去重并清理特殊字符 aspects = list(set([aspect.strip().replace("▁", " ") for aspect in aspects if aspect.strip()])) return aspects def get_sentiment(text: str, aspect: str): """获取指定Aspect的情感标签和得分""" inputs = absa_tokenizer(text, aspect, return_tensors="pt", truncation=True, max_length=512) with torch.inference_mode(): outputs = absa_model(**inputs) scores = F.softmax(outputs.logits[0], dim=-1) label_id = torch.argmax(scores).item() sentiment_label = absa_model.config.id2label[label_id] sentiment_score = scores[label_id].item() return sentiment_label, sentiment_score # 处理DataFrame generated_aspects_list = [] generated_sentiments_list = [] for _, row in df.iterrows(): text = row["text"] predefined_aspects = row["aspects"] # 确定要处理的Aspect:有预定义则用预定义,否则自动提取 target_aspects = predefined_aspects if predefined_aspects else extract_aspects(text) # 处理每个Aspect的情感 sentiment_results = [] for aspect in target_aspects: label, score = get_sentiment(text, aspect) sentiment_results.append(f"{aspect}: {label} (得分: {round(score, 4)})") generated_aspects_list.append(target_aspects) generated_sentiments_list.append(sentiment_results) # 添加新列到DataFrame df["generated_aspects"] = generated_aspects_list df["generated_sentiments"] = generated_sentiments_list # 打印结果 print(df)
代码说明
- Aspect提取:通过
yangheng/deberta-v3-base-aspect-extractor的Token分类功能,识别文本中属于Aspect的连续token,拼接后清理格式并去重。 - 情感分析:对每个Aspect(预定义或自动提取),调用ABSA模型计算情感标签和置信度得分,用
softmax转换为概率值作为情感得分。 - DataFrame处理:遍历每行数据,根据是否有预定义Aspect选择对应逻辑,将结果存入新增列。
注意事项
- 确保安装依赖库:
pip install torch transformers pandas - 首次运行会自动下载模型权重,需保证网络通畅
- 可根据文本长度调整
max_length参数,适配更长文本
内容的提问来源于stack exchange,提问作者Dexter1611
相关产品推荐
相关产品推荐

