跳到主要内容

使用嵌入进行零样本分类

nbviewer

在这个笔记本中,我们将使用嵌入和零标记数据来对评论的情感进行分类!数据集是在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)

# 将5星评级转换为二元情感
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

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

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

使用搜索嵌入和描述性名称会进一步提高性能。

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

如上所示,使用嵌入进行零样本分类可以取得很好的结果,特别是当标签比简单的单词更具描述性时。