2022年3月10日

使用嵌入进行零样本分类

, ,

在本笔记本中,我们将使用嵌入技术和零标注数据来对评论情感进行分类!数据集是在Get_embeddings_from_dataset Notebook中创建的。

我们将4星和5星评价定义为正面情绪,1星和2星评价定义为负面情绪。3星评价被视为中性评价,本示例中不会使用。

我们将通过嵌入每个类别的描述,然后将新样本与这些类别嵌入进行比较,来进行零样本分类。

import pandas as pd
import numpy as np
from ast import literal_eval

from sklearn.metrics import classification_report

EMBEDDING_MODEL = "text-embedding-3-small"

datafile_path = "data/fine_food_reviews_with_embeddings_1k.csv"

df = pd.read_csv(datafile_path)
df["embedding"] = df.embedding.apply(literal_eval).apply(np.array)

# convert 5-star rating to binary sentiment
df = df[df.Score != 3]
df["sentiment"] = df.Score.replace({1: "negative", 2: "negative", 4: "positive", 5: "positive"})

零样本分类

要进行零样本分类,我们希望在没有任何训练的情况下预测样本的标签。为此,我们可以简单地嵌入每个标签的简短描述(例如正面和负面),然后比较样本嵌入与标签描述之间的余弦距离。

与样本输入相似度最高的标签即为预测标签。我们还可以定义一个预测分数,作为与正标签和负标签的余弦距离之差。该分数可用于绘制精确率-召回率曲线,通过选择不同的阈值来调整精确率和召回率之间的权衡。

from utils.embeddings_utils import cosine_similarity, get_embedding
from sklearn.metrics import PrecisionRecallDisplay

def evaluate_embeddings_approach(
    labels = ['negative', 'positive'],
    model = EMBEDDING_MODEL,
):
    label_embeddings = [get_embedding(label, model=model) for label in labels]

    def label_score(review_embedding, label_embeddings):
        return cosine_similarity(review_embedding, label_embeddings[1]) - cosine_similarity(review_embedding, label_embeddings[0])

    probas = df["embedding"].apply(lambda x: label_score(x, label_embeddings))
    preds = probas.apply(lambda x: 'positive' if x>0 else 'negative')

    report = classification_report(df.sentiment, preds)
    print(report)

    display = PrecisionRecallDisplay.from_predictions(df.sentiment, probas, pos_label='positive')
    _ = display.ax_.set_title("2-class Precision-Recall curve")

evaluate_embeddings_approach(labels=['negative', 'positive'], model=EMBEDDING_MODEL)
              precision    recall  f1-score   support

    negative       0.54      0.92      0.68       136
    positive       0.98      0.87      0.92       789

    accuracy                           0.87       925
   macro avg       0.76      0.89      0.80       925
weighted avg       0.92      0.87      0.89       925

image generated by notebook

我们可以看到这个分类器已经表现得非常出色。我们使用了相似性嵌入和最简单的标签名称。让我们尝试通过使用更具描述性的标签名称和搜索嵌入来进一步改进它。

evaluate_embeddings_approach(labels=['An Amazon review with a negative sentiment.', 'An Amazon review with a positive sentiment.'])
              precision    recall  f1-score   support

    negative       0.76      0.96      0.85       136
    positive       0.99      0.95      0.97       789

    accuracy                           0.95       925
   macro avg       0.88      0.96      0.91       925
weighted avg       0.96      0.95      0.95       925

image generated by notebook

使用搜索嵌入和描述性名称可以进一步提升性能。

evaluate_embeddings_approach(labels=['An Amazon review with a negative sentiment.', 'An Amazon review with a positive sentiment.'])
              precision    recall  f1-score   support

    negative       0.76      0.96      0.85       136
    positive       0.99      0.95      0.97       789

    accuracy                           0.95       925
   macro avg       0.88      0.96      0.91       925
weighted avg       0.96      0.95      0.95       925

image generated by notebook

如上所示,使用嵌入进行零样本分类可以带来出色的结果,尤其是当标签不仅仅是简单词汇而是更具描述性时。