实操大型语言模型——文本分类

文本分类是自然语言处理中的常见任务。其目标是训练模型为输入文本分配一个标签或类别(见图4-1)。文本分类在全球范围内广泛应用于各种场景,从情感分析和意图检测到实体提取和语言检测。语言模型(无论是表示型还是生成型)对文本分类的影响不可忽视。

在本章中,我们将讨论多种使用语言模型进行文本分类的方法。这将作为一个易于理解的介绍,帮助你使用已经训练好的语言模型。由于文本分类领域非常广泛,我们将讨论几种技术,并通过它们探索语言模型的应用:

  • "使用表示模型进行文本分类" 展示了非生成型模型在分类任务中的灵活性。我们将介绍特定任务模型和嵌入模型。
  • "使用生成模型进行文本分类" 介绍了生成型语言模型,因大多数生成模型也可以用于分类。我们将介绍一个开源语言模型和一个闭源语言模型。

在本章中,我们将重点利用预训练语言模型,即已经在大量数据上训练好的模型来进行文本分类。正如图4-2所示,我们将考察表示模型和语言模型,并探讨它们的差异。

本章作为生成型和非生成型语言模型的介绍。我们将接触到用于加载和使用这些模型的常见工具包。

电影评论的情感分析

你可以在 Hugging Face Hub 上找到我们用来探索文本分类技术的数据,该平台不仅用于托管模型,还提供数据集。我们将使用知名的"rotten_tomatoes"数据集来训练和评估我们的模型。该数据集包含来自 Rotten Tomatoes 的 5,331 条正面评论和 5,331 条负面评论。

要加载这些数据,我们使用 datasets 包,这将在整本书中使用:

ini 复制代码
from datasets import load_dataset

# 加载数据
data = load_dataset("rotten_tomatoes")
data

输出结果:

css 复制代码
DatasetDict({
    train: Dataset({
        features: ['text', 'label'],
        num_rows: 8530
    })
    validation: Dataset({
        features: ['text', 'label'],
        num_rows: 1066
    })
    test: Dataset({
        features: ['text', 'label'],
        num_rows: 1066
    })
})

数据被分为训练集(train)、测试集(test)和验证集(validation)。在本章中,我们将使用训练集来训练模型,使用测试集来验证结果。需要注意的是,如果你在训练和测试集上进行了超参数调整,可以使用额外的验证集进一步验证模型的泛化能力。

让我们看看训练集中的一些示例:

css 复制代码
data["train"][0, -1]

输出结果:

vbnet 复制代码
{'text': ['the rock is destined to be the 21st century's new " conan " and that he's going to make a splash even greater than arnold schwarzenegger , jean-claud van damme or steven segal .',
  'things really get weird , though not particularly scary : the movie is all portent and no content .'],
 'label': [1, 0]}

这些简短的评论被标记为正面(1)或负面(0)。这意味着我们将专注于二元情感分类任务。

使用表示模型进行文本分类

使用预训练的表示模型进行分类通常有两种方式:使用特定任务模型嵌入模型。正如我们在前一章中探讨的那样,这些模型是通过微调基础模型(例如BERT)来处理特定的下游任务构建的,如图4-3所示。

特定任务模型 是为特定任务(如情感分析)训练的表示模型,例如BERT。正如我们在第1章中探讨的,嵌入模型生成通用的嵌入,可用于不限于分类的各种任务,如语义搜索(参见第8章)。

微调BERT模型用于分类的过程将在第11章中介绍,而创建嵌入模型将在第10章中介绍。在本章中,我们将保持这两种模型冻结(即不可训练状态),只使用它们的输出,如图4-4所示。

我们将利用其他人已经为我们微调好的预训练模型,并探索如何使用它们来对我们选定的电影评论进行分类。

模型选择

在Hugging Face Hub上有超过60,000个用于文本分类的模型,以及8,000多个生成嵌入的模型(撰写本文时的数据),因此选择合适的模型并不像你想象的那样简单。此外,选择适合你的用例的模型至关重要,需要考虑其语言兼容性、底层架构、规模和性能。

首先,让我们从底层架构开始。正如我们在第1章中探讨的,BERT是一种著名的仅编码器架构,是创建特定任务模型和嵌入模型的热门选择。虽然GPT系列等生成模型非常出色,但仅编码器模型在特定任务场景中同样表现优异,并且通常体积要小得多。

多年来,开发了许多BERT的变体,包括RoBERTa、DistilBERT、ALBERT和DeBERTa,每一个都在不同的背景下进行训练。你可以在图4-5中找到一些知名BERT类模型的概览。

选择合适的模型本身就像是一门艺术。由于不可能尝试Hugging Face Hub上的数千个预训练模型,因此我们需要有效地选择模型。话虽如此,有几个模型是很好的起点,可以让你了解此类模型的基本性能。将它们视为稳固的基线模型:

  • BERT 基础模型(uncased)
  • RoBERTa 基础模型
  • DistilBERT 基础模型(uncased)
  • DeBERTa 基础模型
  • bert-tiny
  • ALBERT base v2

对于特定任务模型,我们选择了Twitter-RoBERTa-base情感分析模型。这是一个在推文上微调的RoBERTa模型,专用于情感分析。虽然该模型并非专门为电影评论训练,但探索其泛化能力是很有趣的。

在选择生成嵌入的模型时,MTEB排行榜 是一个很好的起点。它包含了在多个任务上基准测试的开源和闭源模型。除了性能外,还要确保考虑推理速度的重要性,在实际解决方案中推理速度不可低估。因此,在本节中我们将使用 sentence-transformers/all-mpnet-base-v2 作为嵌入模型。这是一个小巧但性能优异的模型。

使用特定任务模型

现在我们已经选择了特定任务的表示模型,接下来让我们加载模型:

ini 复制代码
from transformers import pipeline

# HF模型的路径
model_path = "cardiffnlp/twitter-roberta-base-sentiment-latest"

# 将模型加载到pipeline中
pipe = pipeline(
    model=model_path,
    tokenizer=model_path,
    return_all_scores=True,
    device="cuda:0"
)

在加载模型的同时,我们也加载了分词器,它负责将输入文本转换为单独的词元,如图4-6所示。虽然这一参数并非必须手动加载(它会自动加载),但这展示了模型在背后所进行的操作。

这些词元是大多数语言模型的核心内容,正如我们在第2章中深入探讨的那样。词元的一个主要优势是,即使它们不在训练数据中,也可以通过组合生成表示,如图4-7所示。

在加载所有必要的组件之后,我们可以使用模型对数据的测试集进行推理:

ini 复制代码
import numpy as np
from tqdm import tqdm
from transformers.pipelines.pt_utils import KeyDataset

# 运行推理
y_pred = []
for output in tqdm(pipe(KeyDataset(data["test"], "text")), total=len(data["test"])):
    negative_score = output[0]["score"]
    positive_score = output[2]["score"]
    assignment = np.argmax([negative_score, positive_score])
    y_pred.append(assignment)

现在我们已经生成了预测结果,接下来就是进行评估。我们创建一个小函数,方便在本章中重复使用:

python 复制代码
from sklearn.metrics import classification_report

def evaluate_performance(y_true, y_pred):
    """创建并打印分类报告"""
    performance = classification_report(
        y_true, y_pred,
        target_names=["Negative Review", "Positive Review"]
    )
    print(performance)

接下来,生成我们的分类报告:

css 复制代码
evaluate_performance(data["test"]["label"], y_pred)

输出结果:

yaml 复制代码
                precision    recall  f1-score   support

Negative Review       0.76      0.88      0.81       533
Positive Review       0.86      0.72      0.78       533

       accuracy                           0.80      1066
      macro avg       0.81      0.80      0.80      1066
   weighted avg       0.81      0.80      0.80      1066

要理解生成的分类报告,我们首先需要探索如何识别正确和错误的预测。根据预测是否正确(True)或错误(False),以及我们预测的类别是正确类(Positive)还是错误类(Negative),有四种组合。我们可以将这些组合用矩阵表示,通常称为混淆矩阵,如图4-8所示。

通过混淆矩阵,我们可以推导出几个公式来描述模型的质量。在前面生成的分类报告中,我们可以看到四种方法,分别是精确率 (precision)、召回率 (recall)、准确率 (accuracy)和F1分数

  • 精确率 衡量找到的项目中有多少是相关的,表示相关结果的准确性。
  • 召回率 指找到的相关类别有多少,表示模型发现所有相关结果的能力。
  • 准确率 衡量模型在所有预测中做出的正确预测的比例,表示模型的整体正确性。
  • F1分数 结合了精确率和召回率,来评估模型的整体性能。

这些四种指标在图4-9中进行了说明,图中使用了前面提到的分类报告来描述它们。

在本书的示例中,我们将考虑F1分数的加权平均值,以确保每个类别得到公平对待。我们的预训练BERT模型给出的F1分数为0.80(可以从加权平均行的F1分数列读取),对于没有专门针对我们领域数据进行训练的模型来说,这已经相当不错了!

为了提升所选模型的性能,我们可以采取一些措施,比如选择一个专门针对我们领域数据(例如电影评论)训练的模型,如DistilBERT base uncased fine-tuned SST-2 。我们也可以将重点转向另一类表示模型,即嵌入模型

利用嵌入的分类任务

在前面的例子中,我们使用了预训练的特定任务模型来进行情感分析。然而,如果我们找不到为特定任务预训练的模型呢?是否需要自己微调一个表示模型?答案是否定的!

如果你有足够的计算资源,可能有时会想自己微调模型(参见第11章)。然而,并非所有人都有大量的计算资源可用。这时,通用嵌入模型就派上用场了。

监督分类

与前面的例子不同,我们可以通过采用更经典的方式,自己执行部分训练过程。与直接使用表示模型进行分类不同,我们将使用嵌入模型来生成特征。这些特征可以传递给分类器,从而创建一个两步法,如图4-10所示。

这种分离的一个主要好处是我们不需要微调嵌入模型,因为微调可能非常昂贵。相反,我们可以在CPU上训练一个分类器,例如逻辑回归。

在第一步中,我们使用嵌入模型将文本输入转换为嵌入,如图4-11所示。需要注意的是,这个模型同样保持冻结状态,并且不会在训练过程中进行更新。

我们可以使用 sentence-transformer 这个流行的包来利用预训练的嵌入模型,生成嵌入的过程很简单:

ini 复制代码
from sentence_transformers import SentenceTransformer

# 加载模型
model = SentenceTransformer("sentence-transformers/all-mpnet-base-v2")

# 将文本转换为嵌入
train_embeddings = model.encode(data["train"]["text"], show_progress_bar=True)
test_embeddings = model.encode(data["test"]["text"], show_progress_bar=True)

正如我们在第1章中讨论的,嵌入是输入文本的数值表示。嵌入的数值数量(或维度)取决于底层的嵌入模型。让我们来看看我们模型的嵌入维度:

train_embeddings.shape

输出结果为:

scss 复制代码
(8530, 768)

这表明我们的8,530个输入文档中的每一个都有768维的嵌入,因此每个嵌入包含768个数值。

在第二步中,这些嵌入作为分类器的输入特征,如图4-12所示。分类器是可训练的,不限于逻辑回归,只要能执行分类任务,分类器可以采用任何形式。

我们将此步骤保持简单,并使用逻辑回归作为分类器。要训练分类器,我们只需使用生成的嵌入和标签:

css 复制代码
from sklearn.linear_model import LogisticRegression

# 使用训练集嵌入训练逻辑回归模型
clf = LogisticRegression(random_state=42)
clf.fit(train_embeddings, data["train"]["label"])

接下来,评估模型:

ini 复制代码
# 预测测试集中的未见实例
y_pred = clf.predict(test_embeddings)
evaluate_performance(data["test"]["label"], y_pred)

输出结果为:

yaml 复制代码
              precision    recall  f1-score   support

Negative Review       0.85      0.86      0.85       533
Positive Review       0.86      0.85      0.85       533

       accuracy                           0.85      1066
      macro avg       0.85      0.85      0.85      1066
   weighted avg       0.85      0.85      0.85      1066

通过在嵌入上训练分类器,我们获得了0.85的F1分数!这展示了在保持底层嵌入模型冻结的情况下,训练轻量级分类器的可能性。

提示:

在这个例子中,我们使用了sentence-transformers来提取嵌入,它可以借助GPU加速推理。然而,如果想移除对GPU的依赖,可以使用外部API生成嵌入。常见的选择有Cohere和OpenAI的嵌入服务。这样,整个流程可以完全在CPU上运行。

如果我们没有标签数据怎么办?

在前面的例子中,我们有可用的标签数据,但在实践中,这种情况可能并不常见。获取标签数据是一个资源密集型的任务,通常需要大量的人工劳动。此外,收集这些标签是否真的值得?

为了测试这一点,我们可以进行零样本分类(zero-shot classification),即在没有标签数据的情况下探索任务是否可行。尽管我们知道标签的定义(即它们的名称),但并没有相应的标签数据支持。零样本分类尝试预测输入文本的标签,即使模型从未在这些标签上进行过训练,如图4-13所示。

要使用嵌入进行零样本分类,我们可以使用一个巧妙的技巧。我们可以基于标签应代表的内容来描述它们。例如,电影评论中的负面标签可以描述为"这是一个负面的电影评论"。通过对标签和文档进行描述和嵌入处理,我们就有了可用于工作的数据。这个过程如图4-14所示,允许我们生成自己的目标标签,而无需实际拥有任何标签数据。

我们可以像之前一样使用 .encode 函数来创建这些标签的嵌入:

ini 复制代码
# 为标签创建嵌入
label_embeddings = model.encode(["A negative review",  "A positive review"])

为了将标签分配给文档,我们可以对文档和标签对应用余弦相似度。余弦相似度是向量之间夹角的余弦值,通过嵌入的点积除以它们长度的乘积来计算,如图4-15所示。

我们可以使用余弦相似度来检查给定文档与候选标签描述的相似度。选择与文档相似度最高的标签作为最终标签,如图4-16所示。

要在嵌入上执行余弦相似度比较,我们只需将文档嵌入与标签嵌入进行比较,找到最匹配的对:

ini 复制代码
from sklearn.metrics.pairwise import cosine_similarity

# 为每个文档找到最匹配的标签
sim_matrix = cosine_similarity(test_embeddings, label_embeddings)
y_pred = np.argmax(sim_matrix, axis=1)

就这样!我们只需为标签命名即可执行分类任务。让我们看看这种方法的效果如何:

css 复制代码
evaluate_performance(data["test"]["label"], y_pred)

输出结果为:

yaml 复制代码
                precision    recall  f1-score   support

Negative Review       0.78      0.77      0.78       533
Positive Review       0.77      0.79      0.78       533

       accuracy                           0.78      1066
      macro avg       0.78      0.78      0.78      1066
   weighted avg       0.78      0.78      0.78      1066

注意

如果你熟悉基于Transformer模型的零样本分类,你可能会好奇为什么我们选择通过嵌入来演示这一点。尽管自然语言推理模型在零样本分类中表现出色,但这里的例子展示了嵌入的灵活性,可用于各种任务。正如你在本书中将看到的,嵌入几乎存在于所有语言AI用例中,往往是被低估但极其重要的组件。

考虑到我们没有使用任何标签数据,0.78的F1分数相当令人印象深刻!这展示了嵌入的多功能性和实用性,尤其是当你能稍微发挥一些创造力时。

提示

让我们测试一下这种创造力。我们使用了"A negative/positive review "作为标签名称,但这可以进一步改进。我们可以使其更具体一点,使用"A very negative/positive movie review",这样嵌入会捕捉到它是关于电影评论的,并更侧重于两个标签的极端。尝试一下,看看它如何影响结果。

使用生成模型进行文本分类

使用生成语言模型(如OpenAI的GPT模型)进行分类的方式与我们之前的做法有所不同。这些模型接受输入文本并生成文本,因此被称为序列到序列模型(sequence-to-sequence models)。这与我们的特定任务模型形成鲜明对比,后者直接输出一个类别,如图4-17所示。

这些生成模型通常经过广泛的任务训练,通常无法直接执行你的特定用例。例如,如果我们给生成模型提供一段没有任何上下文的电影评论,它并不知道该如何处理。

相反,我们需要帮助它理解上下文,并引导它生成我们想要的答案。正如图4-18所示,这一引导过程主要通过你提供给模型的指令提示 来完成。通过迭代改进提示以获得所需的输出,这个过程被称为提示工程(prompt engineering)。

在本节中,我们将展示如何利用不同类型的生成模型在没有Rotten Tomatoes数据集的情况下执行分类任务。

使用文本到文本的转换模型(Text-to-Text Transfer Transformer)

在本书中,我们将主要探索仅编码器模型 (如BERT)和仅解码器模型 (如ChatGPT)。然而,正如我们在第1章讨论的,最初的Transformer架构实际上是编码器-解码器 架构。与仅解码器模型类似,这些编码器-解码器模型也是序列到序列模型,通常属于生成模型的范畴。

一个有趣的利用这种架构的模型系列是文本到文本转换Transformer(T5)模型。如图4-19所示,其架构类似于最初的Transformer,其中12个解码器和12个编码器堆叠在一起【7】。

使用这种架构,这些模型首先通过掩码语言模型进行预训练。在训练的第一步中,如图4-20所示,与掩盖单个词元不同,预训练过程中掩盖的是一组词元(或词元跨度)。

训练的第二步,也就是微调基础模型 ,是实现模型强大功能的关键所在。与仅为某个特定任务进行微调不同,每个任务都被转换为序列到序列任务并同时进行训练。正如图4-21所示,这使得模型能够在各种不同的任务上进行训练。

这种微调方法在论文《Scaling instruction-finetuned language models》中得到了扩展,在微调过程中引入了超过一千个任务,这些任务更接近我们从GPT模型中熟悉的指令【8】。这催生了Flan-T5模型家族,它从多样化的任务中受益。

要使用预训练的Flan-T5模型进行分类,我们首先通过"text2text-generation"任务加载它,这通常用于这些编码器-解码器模型:

ini 复制代码
# 加载模型
pipe = pipeline(
    "text2text-generation", 
    model="google/flan-t5-small", 
    device="cuda:0"
)

Flan-T5模型有不同的规模(flan-t5-small/base/large/xl/xxl),为了加快速度,我们使用了最小的版本。不过,欢迎你尝试更大的模型以查看是否能改进结果。

与我们的特定任务模型相比,我们不能只给模型提供一些文本并期望它输出情感结果。相反,我们需要指示模型进行操作。因此,我们在每个文档前加上提示:"这个句子是正面还是负面的?":

ini 复制代码
# 准备数据
prompt = "Is the following sentence positive or negative? "
data = data.map(lambda example: {"t5": prompt + example['text']})
data

生成的数据集:

css 复制代码
DatasetDict({
    train: Dataset({
        features: ['text', 'label', 't5'],
        num_rows: 8530
    })
    validation: Dataset({
        features: ['text', 'label', 't5'],
        num_rows: 1066
    })
    test: Dataset({
        features: ['text', 'label', 't5'],
        num_rows: 1066
    })
})

更新数据后,我们可以像在特定任务示例中那样运行推理管道:

ini 复制代码
# 运行推理
y_pred = []
for output in tqdm(pipe(KeyDataset(data["test"], "t5")), total=len(data["test"])):
    text = output[0]["generated_text"]
    y_pred.append(0 if text == "negative" else 1)

由于该模型生成文本,我们需要将文本输出转换为数值。"negative"对应0,"positive"对应1。

这些数值允许我们像以前一样测试模型的质量:

css 复制代码
evaluate_performance(data["test"]["label"], y_pred)

输出结果:

yaml 复制代码
                precision    recall  f1-score   support

Negative Review       0.83      0.85      0.84       533
Positive Review       0.85      0.83      0.84       533

       accuracy                           0.84      1066
      macro avg       0.84      0.84      0.84      1066
   weighted avg       0.84      0.84      0.84      1066

F1分数达到0.84,显然Flan-T5模型在展示生成模型能力方面表现出色。

使用ChatGPT进行分类

虽然本书主要聚焦于开源模型,但语言AI领域的另一个重要组成部分是闭源模型,特别是ChatGPT。

尽管ChatGPT原始模型(GPT-3.5)的底层架构没有公开,但从其名称可以推测,它基于我们在GPT模型中见过的仅解码器架构

幸运的是,OpenAI分享了该模型训练过程的概述,其中包括一个关键组件,即偏好微调。正如图4-22所示,OpenAI首先手动创建了输入提示的期望输出(指令数据),并使用这些数据来创建其模型的初始版本。

OpenAI 使用生成的模型输出多个结果,并对这些结果进行手动排名,从最好到最差。正如图4-23所示,这种排名表明了对某些输出的偏好(偏好数据),并用于创建最终模型------ChatGPT。

使用偏好数据(而不是指令数据)的一个主要优势是它能捕捉细微差别。通过展示更好和较好输出之间的区别,生成模型学会生成符合人类偏好的文本。在第12章中,我们将深入探讨这些微调和偏好微调方法的工作原理,并了解如何自行执行这些操作。

使用闭源模型的过程与我们之前看到的开源模型示例有所不同。我们无需加载模型,而是通过OpenAI的API进行访问。

在开始分类示例之前,你需要先在 OpenAI官网 注册一个免费账户,并在 此处 创建一个API密钥。完成后,你可以使用这个API密钥与OpenAI服务器进行通信。

我们可以使用这个密钥来创建一个客户端:

ini 复制代码
import openai

# 创建客户端
client = openai.OpenAI(api_key="YOUR_KEY_HERE")

使用此客户端,我们可以创建一个 chatgpt_generation 函数,允许我们根据指定的提示、输入文档以及选定的模型生成文本:

ini 复制代码
def chatgpt_generation(prompt, document, model="gpt-3.5-turbo-0125"):
    """基于提示和输入文档生成输出。"""
    messages = [
        {
            "role": "system",
            "content": "You are a helpful assistant."
        },
        {
            "role": "user",
            "content": prompt.replace("[DOCUMENT]", document)
        }
    ]
    chat_completion = client.chat.completions.create(
        messages=messages,
        model=model,
        temperature=0
    )
    return chat_completion.choices[0].message.content

接下来,我们需要创建一个模板来指示模型执行分类任务:

ini 复制代码
# 定义一个基础的提示模板
prompt = """Predict whether the following document is a positive or negative movie review:

[DOCUMENT]

If it is positive return 1 and if it is negative return 0. Do not give any other answers.
"""

# 使用GPT进行预测
document = "unpretentious , charming , quirky , original"
chatgpt_generation(prompt, document)

这个模板只是一个示例,可以根据需要进行修改。为了简单起见,我们保持它的内容尽量简洁,以展示如何使用此类模板。

在处理可能较大的数据集之前,请务必跟踪你的使用情况。像OpenAI这样的外部API如果执行大量请求,成本可能会快速上升。截至撰写本文时,使用"gpt-3.5-turbo-0125"模型运行我们的测试数据集的费用为3美分(免费账户涵盖该费用),但未来可能会有变化。

提示 处理外部API时,你可能会遇到速率限制错误。当你调用API过于频繁时,某些API可能会限制每分钟或每小时的调用次数。为防止这些错误,我们可以实现一些重试机制,包括所谓的指数回退。每当遇到速率限制错误时,进行短暂的休眠并重试失败的请求。如果再次失败,则增加休眠时间,直到请求成功或达到最大重试次数。

接下来,我们可以对测试数据集中的所有评论运行此函数以获取预测结果。如果你想将(免费的)额度保留给其他任务,可以跳过此步骤。

ini 复制代码
# 如果想节省(免费)额度,可以跳过此步骤
predictions = [
    chatgpt_generation(prompt, doc) for doc in tqdm(data["test"]["text"])
]

和前面的示例一样,我们需要将字符串输出转换为整数,以评估其性能:

ini 复制代码
# 提取预测结果
y_pred = [int(pred) for pred in predictions]

# 评估性能
evaluate_performance(data["test"]["label"], y_pred)

输出结果:

yaml 复制代码
                precision    recall  f1-score   support

Negative Review       0.87      0.97      0.92       533
Positive Review       0.96      0.86      0.91       533

       accuracy                           0.91      1066
      macro avg       0.92      0.91      0.91      1066
   weighted avg       0.92      0.91      0.91      1066

F1分数为0.91,已经展示了该模型在生成式AI领域的卓越性能。然而,由于我们不知道模型的训练数据集,无法轻易使用这些指标来评估模型。我们不知道该模型是否实际在我们的数据集上进行过训练!

在第12章中,我们将探讨如何在更广泛的任务上评估开源和闭源模型。

总结

在本章中,我们讨论了执行各种分类任务的多种技术,从对整个模型进行微调到完全不需要微调!文本分类并不像表面上看起来那么简单,实际上有许多富有创造力的技术可以实现。

我们在本章中探索了使用生成语言模型表示语言模型进行文本分类。我们的目标是为输入文本分配标签或类别,以分类评论的情感。

我们探讨了两种表示模型:特定任务模型嵌入模型。特定任务模型在一个专门用于情感分析的大型数据集上进行了预训练,向我们展示了预训练模型是进行文档分类的一个很好的方法。嵌入模型用于生成多用途嵌入,我们使用这些嵌入作为输入来训练分类器。

同样,我们还探索了两种生成模型:一个开源的编码器-解码器模型 (Flan-T5)和一个闭源的仅解码器模型(GPT-3.5)。我们在文本分类中使用了这些生成模型,而不需要对领域数据或标签数据集进行特定(额外)的训练。

在下一章中,我们将继续讨论分类,但重点放在无监督分类上。如果我们没有任何标签的文本数据,我们可以做什么?我们可以提取哪些信息?我们将重点讨论数据的聚类以及使用主题建模技术为聚类命名。

相关推荐
视觉人机器视觉7 分钟前
爸妈总说着学门技术,学机器视觉技术确实是一条踏实的生活道路,这条路你走得下去走得通吗?
人工智能·算法·计算机视觉·c#·自动化
熬夜造bug1 小时前
计算机视觉——图像修复综述篇
人工智能·计算机视觉
明志刘明1 小时前
昇思MindSpore进阶教程--数据处理性能优化(中)
人工智能·深度学习·机器学习·性能优化·mindspore·昇思
Francek Chen1 小时前
【机器学习-无监督学习】概率图模型
人工智能·机器学习·scikit-learn·贝叶斯网络·naive bayes·马尔可夫网络
z千鑫1 小时前
【Cursor文档】Cursor中文官方文档教程(官方功能介绍)
开发语言·人工智能·ai编程·corsor·codemoss能用ai
rubyw2 小时前
机器学习:序列模式算法的原理、应用场景及优缺点介绍
人工智能·算法·机器学习
SEVEN-YEARS2 小时前
LSTM(长短时记忆网络)
深度学习·lstm
sniper_fandc2 小时前
深度学习基础—卷积神经网络示例
人工智能·深度学习·cnn
拥抱AGI2 小时前
大厂养不起大模型?
人工智能·学习·大模型·ai大模型·大模型学习·大模型入门·大模型教程
码农超哥同学2 小时前
Python知识点:结合Python工具,如何使用GPT进行文本生成
开发语言·人工智能·python·gpt·语言模型·面试·编程