Как сгенерировать оценки настроений, используя предопределенные аспекты с помощью модели deberta-v3-base-absa-v1.1 Huggingface?

У меня есть фрейм данных, где есть текст в 1-м столбце и предопределенный аспект в другом столбце, однако для нескольких текстов, например, строки 2, не определены аспекты.

      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)

Я хочу создать две вещи

  1. используя предварительно заданный аспект для текста, сгенерируйте оценку настроения
  2. используя аспект генерации текста, а также оценку настроений из пакета

Примечание. Этот пакет yangheng/deberta-v3-base-absa-v1.1.

1) генерировать оценку настроений на основе заранее определенных аспектов

2) генерировать оба аспекта и соответствующие чувства

Примечание. В строке 2 нет предопределенного аспекта.

Я попробовал и получил ошибку

      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)

Желаемый результат

1 ответ

Специально дляyangheng/deberta-v3-base-absa-v1.1модель, это использование, и вам нужно пройти через модель один раз для каждого аспекта:

      # 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)

classifier = pipeline("text-classification", model=model, tokenizer=tokenizer)


for aspect in ['camera', 'phone']:
   print(aspect, classifier('The camera quality of this phone is amazing.',  text_pair=aspect))

[вне]:

      camera [{'label': 'Positive', 'score': 0.9967294931411743}]
phone [{'label': 'Neutral', 'score': 0.9472787380218506}]

Чтобы получить баллы классификации с нулевым выстрелом в целом, попробуйте использоватьpipeline:

      from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import pipeline


# 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)


pipe = pipeline("zero-shot-classification", model=model, tokenizer=tokenizer)

pipe("The camera quality of this phone is amazing.", candidate_labels=["camera", "phone"])

[вне]:

      {'sequence': 'The camera quality of this phone is amazing.',
 'labels': ['camera', 'phone'],
 'scores': [0.9036691784858704, 0.09633082151412964]}

В зависимости от того, что означает «аспект сгенерированного текста», возможно, это извлечение ключевых слов, и если да, то выполнение поиска на https://huggingface.co/models?search=keyword дает это как самую загружаемую модель, https://huggingface.co/yanekyuk/bert-uncased-keyword-extractor

      from transformers import AutoTokenizer, AutoModelForTokenClassification

tokenizer2 = AutoTokenizer.from_pretrained("yanekyuk/bert-uncased-keyword-extractor")
model2 = AutoModelForTokenClassification.from_pretrained("yanekyuk/bert-uncased-keyword-extractor")



def extract_aspect(text):
    extractor = pipeline("ner", model=model2, tokenizer=tokenizer2)
    phrasesids = []
    for tag in extractor(text):
        if tag['entity'].startswith('B'):
            phrasesids.append([tag['start'], tag['end']])
        if tag['entity'].startswith('I'):
            phrasesids[-1][-1] = tag['end']
    phrases = [text[p[0]:p[1]] for p in phrasesids]
    return phrases

text = "The camera quality of this phone is amazing."

extract_aspect(text)

[вне]:

      camera

Собираем экстрактор и классификатор вместе:

      from transformers import AutoTokenizer, AutoModelForSequenceClassification, AutoModelForTokenClassification
from transformers import pipeline


# 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)

classifier = pipeline("zero-shot-classification", model=model, tokenizer=tokenizer)

tokenizer2 = AutoTokenizer.from_pretrained("yanekyuk/bert-uncased-keyword-extractor")
model2 = AutoModelForTokenClassification.from_pretrained("yanekyuk/bert-uncased-keyword-extractor")


def extract_aspect(text):
    extractor = pipeline("ner", model=model2, tokenizer=tokenizer2)
    phrasesids = []
    for tag in extractor(text):
        if tag['entity'].startswith('B'):
            phrasesids.append([tag['start'], tag['end']])
        if tag['entity'].startswith('I'):
            phrasesids[-1][-1] = tag['end']
    phrases = [text[p[0]:p[1]] for p in phrasesids]
    return phrases

text = "The camera quality of this phone is amazing."

pipe(text, candidate_labels=extract_aspect(text))

[вне]:

      {'sequence': 'The camera quality of this phone is amazing.',
 'labels': ['camera'],
 'scores': [0.9983300566673279]}

Вопрос: Но извлеченные ключевые слова не являются «правильными» или не соответствуют заранее определенным?

Ответ: Ни одна модель не идеальна, и приведенный выше пример модели представляет собой экстрактор ключевых слов, а не экстрактор аспектов продукта. ЮММВ.

Вопрос: Почему классификатор нулевого выстрела не дает мне меток «отрицательный/положительный»?

Ответ: Классификатор нулевого выстрела маркирует данные на основе извлеченных меток. Не классификатор настроений.

Другие вопросы по тегам