NLP | 一文搞懂如何微调抱脸(Hugging Face)模型

介绍

微调自然语言处理 (NLP) 模型需要更改模型的超参数和架构,并且通常会调整数据集以提高模型在给定任务上的性能。您可以通过调整学习率、模型中的层数、嵌入的大小以及各种其他参数来实现这一点。微调是一个耗时的过程,需要牢牢掌握模型和工作。本文将介绍如何微调抱脸模型。

学习目标

● 了解 T5 模型的结构,包括变形金刚和自注意力。

● 了解如何优化超参数以获得更好的模型性能。

● 主文本数据准备,包括标记化和格式化。

● 知道如何使预训练模型适应特定任务。

● 了解如何清理、拆分和创建用于训练的数据集。

● 获得使用损失和准确性等指标进行模型训练和评估的经验。

● 探索微调模型在生成响应或答案方面的实际应用。

关于 Hugging Face Models

Hugging Face 是一家为自然语言处理 (NLP) 模型训练和部署提供平台的公司。该平台拥有适用于各种 NLP 任务的模型库,包括语言翻译、文本生成和问答。这些模型在广泛的数据集上接受训练,旨在在广泛的自然语言处理 (NLP) 活动中表现出色。

Hugging Face 平台还包括用于在特定数据集上微调预训练模型的工具,这有助于使算法适应特定领域或语言。该平台还具有用于访问和利用应用程序中预训练模型的 API,以及用于构建定制模型并将其交付到云端的工具。

将 Hugging Face 库用于自然语言处理 (NLP) 任务具有多种优势:

1. 多种型号可供选择: Hugging Face 库提供了大量预训练的 NLP 模型,包括针对语言翻译、问答和文本分类等任务进行训练的模型。这使得选择满足您确切要求的型号变得简单。

2. 跨平台兼容性:Hugging Face 库与 TensorFlow、PyTorch 和 Keras 等标准深度学习系统兼容,可以轻松集成到您现有的工作流程中。

3. 简单的微调: Hugging Face 库包含用于微调数据集上预训练模型的工具,与从头开始训练模型相比,可以节省时间和精力。

4. 活跃的社区: Hugging Face 图书馆拥有庞大而活跃的用户社区,这意味着您可以获得帮助和支持,并为图书馆的发展做出贡献。

5. 有据可查:Hugging Face 库包含大量文档,可以轻松上手并学习如何有效地使用它。

导入必要的库

导入必要的库类似于为特定的编程和数据分析活动构建工具包。这些库通常是预先编写的代码集合,它们提供了广泛的功能和工具,有助于加快开发速度。开发人员和数据科学家可以通过导入适当的库来访问新功能、提高生产力并使用现有解决方案。

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split


import torch

from transformers import T5Tokenizer
from transformers import T5ForConditionalGeneration, AdamW

import pytorch_lightning as pl
from pytorch_lightning.callbacks import ModelCheckpoint

pl.seed_everything(100)

import warnings
warnings.filterwarnings("ignore")

导入数据集

导入数据集是数据驱动项目中至关重要的第一步。

df = pd.read_csv("/kaggle/input/queestion-answer-dataset-qa/train.csv")
df.columns

df = df[['context','question', 'text']]
print("Number of records: ", df.shape[0])

问题陈述

“创建一个能够根据上下文和问题生成响应的模型。”

例如

Context = “例如,对类似病例的聚类组可以找到

相似的患者或用于

银行领域的客户细分。关联技术用于查找经常同时发生的物料或事件

,例如,特定客户通常一起购买的杂货物料。异常检测用于发现异常和异常

情况;例如,信用卡欺诈

检测。

问题 =“异常检测的示例是什么?

答案 = ????????????????????????????????

df["context"] = df["context"].str.lower()
df["question"] = df["question"].str.lower()
df["text"] = df["text"].str.lower()

df.head()

初始化参数

● 输入长度: 在训练过程中,我们将输入到模型中的单个示例中的输入标记(例如单词或字符)的数量称为输入长度。如果要训练语言模型来预测句子中的下一个单词,则输入长度将是短语中的单词数。

● 输出长度: 在训练期间,模型应在单个样本中生成特定数量的输出标记,例如单词或字符。输出长度对应于模型在句子中预测的单词数。

● 训练批量大小:在训练期间,模型一次处理多个样本。如果将训练批次大小设置为 32,则模型会在更新其模型权重之前同时处理 32 个实例,例如 32 个短语。

● 验证批量大小: 与训练批处理大小类似,此参数指示模型在验证阶段处理的实例数。换句话说,它表示模型在保留数据集上进行测试时处理的数据量。

● 时代:一个 epoch 是整个训练数据集的单次行程。因此,如果训练数据集包含 1000 个实例,并且训练批次大小为 32,则一个 epoch 将需要 32 个训练步骤。如果模型训练了 10 个 epoch,它将处理 10000 个实例(10 * 1000 = 10000 个)。

DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 
INPUT_MAX_LEN = 512 # Input length
OUT_MAX_LEN = 128 # Output Length
TRAIN_BATCH_SIZE = 8 # Training Batch Size
VALID_BATCH_SIZE = 2 # Validation Batch Size
EPOCHS = 5 # Number of Iteration

T5 Transformer

T5 模型基于 Transformer 架构,这是一种旨在有效处理顺序输入数据的神经网络。它包括一个编码器和一个解码器,其中包括一系列相互连接的“层”。

编码器和解码器层包括各种“注意力”机制和“前馈”网络。注意力机制使模型能够在其他时间关注输入序列的不同部分。同时,前馈网络使用一组权重和偏差来改变输入数据。

T5 模型还采用了“自注意力”,它允许输入序列中的每个元素注意其他每个元素。这允许模型识别输入数据中单词和短语之间的联系,这对于许多 NLP 应用程序至关重要。

除了编码器和解码器之外,T5 模型还包含一个“语言模型头”,它根据前一个单词预测序列中的下一个单词。这对于翻译和文本制作工作至关重要,在这些工作中,模型必须提供有凝聚力和自然的输出。

除了编码器和解码器之外,T5 模型还包含一个“语言模型头”,它根据前一个单词预测序列中的下一个单词。这对于翻译和文本制作工作至关重要,在这些工作中,模型必须提供有凝聚力和自然的输出。

T5 模型代表了一个大型而复杂的神经网络,旨在高效、准确地处理顺序输入。它在各种文本数据集上进行了广泛的训练,可以熟练地执行广泛的自然语言处理任务。

T5Tokenizer

T5Tokenizer 用于将文本转换为标记列表,每个标记代表一个单词或标点符号。分词器还会在输入文本中插入唯一标记,以表示文本的开始和结束,并区分各种短语。

T5Tokenizer 结合了字符级和单词级分词化,以及与 SentencePiece 分词器相当的子字级分词化策略。它根据训练数据中每个字符或字符序列的频率对输入文本进行子字处理。这有助于分词器处理未出现在训练数据中但出现在测试数据中的词汇外 (OOV) 术语。

T5Tokenizer 还会在文本中插入唯一标记,以表示句子的开头和结尾并划分它们。例如,它添加标记 s > 和 / s > 表示短语的开头和结尾,而填充 > 表示填充。

MODEL_NAME = "t5-base"

tokenizer = T5Tokenizer.from_pretrained(MODEL_NAME, model_max_length= INPUT_MAX_LEN)
print("eos_token: {} and id: {}".format(tokenizer.eos_token,
                   tokenizer.eos_token_id)) # End of token (eos_token)
print("unk_token: {} and id: {}".format(tokenizer.unk_token,
                   tokenizer.eos_token_id)) # Unknown token (unk_token)
print("pad_token: {} and id: {}".format(tokenizer.pad_token,
                 tokenizer.eos_token_id)) # Pad token (pad_token)

数据集准备

在处理 PyTorch 时,通常使用数据集类准备数据以用于模型。数据集类负责从光盘加载数据并执行所需的准备过程,例如标记化和数值化。该类还应实现 getitem 函数,该函数用于按索引从数据集中获取单个项目。 init 方法使用文本列表、标签列表和分词器填充数据集。len 函数返回数据集中的样本数。get item 函数按索引从数据集中返回单个项目。它接受索引 idx 并输出标记化的输入和标签。 通常还包括各种预处理步骤,例如填充和截断标记化输入。您也可以将标签转换为张量。

class T5Dataset:

    def __init__(self, context, question, target):
        self.context = context
        self.question = question
        self.target = target
        self.tokenizer = tokenizer
        self.input_max_len = INPUT_MAX_LEN
        self.out_max_len = OUT_MAX_LEN

    def __len__(self):
        return len(self.context)

    def __getitem__(self, item):
        context = str(self.context[item])
        context = " ".join(context.split())

        question = str(self.question[item])
        question = " ".join(question.split())

        target = str(self.target[item])
        target = " ".join(target.split())


        inputs_encoding = self.tokenizer(
            context,
            question,
            add_special_tokens=True,
            max_length=self.input_max_len,
            padding = 'max_length',
            truncation='only_first',
            return_attention_mask=True,
            return_tensors="pt"
        )


        output_encoding = self.tokenizer(
            target,
            None,
            add_special_tokens=True,
            max_length=self.out_max_len,
            padding = 'max_length',
            truncation= True,
            return_attention_mask=True,
            return_tensors="pt"
        )


        inputs_ids = inputs_encoding["input_ids"].flatten()
        attention_mask = inputs_encoding["attention_mask"].flatten()
        labels = output_encoding["input_ids"]

        labels[labels == 0] = -100  # As per T5 Documentation

        labels = labels.flatten()

        out = {
            "context": context,
            "question": question,
            "answer": target,
            "inputs_ids": inputs_ids,
            "attention_mask": attention_mask,
            "targets": labels
        }


        return out

数据加载器

DataLoader 类以并行和批处理方式加载数据,从而可以处理大型数据集,否则这些数据集将过于庞大而无法存储在内存中。将 DataLoader 类与包含要加载的数据的数据集类组合在一起。

Dataloader 负责遍历数据集,并在训练 transformer 模型时将一批数据返回给模型进行训练或评估。DataLoader 类提供了各种参数来控制数据的加载和预处理,包括批处理大小、工作线程计数以及是否在每个纪元之前对数据进行随机排序。

class T5DatasetModule(pl.LightningDataModule):

    def __init__(self, df_train, df_valid):
        super().__init__()
        self.df_train = df_train
        self.df_valid = df_valid
        self.tokenizer = tokenizer
        self.input_max_len = INPUT_MAX_LEN
        self.out_max_len = OUT_MAX_LEN


    def setup(self, stage=None):

        self.train_dataset = T5Dataset(
        context=self.df_train.context.values,
        question=self.df_train.question.values,
        target=self.df_train.text.values
        )

        self.valid_dataset = T5Dataset(
        context=self.df_valid.context.values,
        question=self.df_valid.question.values,
        target=self.df_valid.text.values
        )

    def train_dataloader(self):
        return torch.utils.data.DataLoader(
         self.train_dataset,
         batch_size= TRAIN_BATCH_SIZE,
         shuffle=True, 
         num_workers=4
        )


    def val_dataloader(self):
        return torch.utils.data.DataLoader(
         self.valid_dataset,
         batch_size= VALID_BATCH_SIZE,
         num_workers=1
        )

模型构建

在 PyTorch 中创建转换器模型时,通常首先创建一个派生自 torch 的新类 -- nn.Module。此类描述模型的体系结构,包括层和转发函数。类的 init 函数定义模型的体系结构,通常通过实例化模型的不同级别并将它们分配为类属性。

正向方法负责在模型中向前传递数据。此方法接受输入数据并应用模型的层来创建输出。forward 方法应实现模型的逻辑,例如通过一系列层传递输入并返回结果。

该类的 init 函数创建一个嵌入层、一个转换器层和一个全连接层,并将它们指定为类属性。forward 方法接受传入的数据 x,通过给定的阶段对其进行处理,并返回结果。训练 transformer 模型时,训练过程通常包括两个阶段:训练和验证。

training_step 方法指定了执行单个训练步骤的基本原理,通常包括:

● 前向传递模型

● 计算损失

● 计算梯度

● 更新模型的参数

val_step 方法与 training_step 方法一样,用于评估验证集上的模型。它通常包括:

● 前向传递模型

● 计算评估指标

class T5Model(pl.LightningModule):

    def __init__(self):
        super().__init__()
        self.model = T5ForConditionalGeneration.from_pretrained(MODEL_NAME, return_dict=True)

    def forward(self, input_ids, attention_mask, labels=None):

        output = self.model(
            input_ids=input_ids, 
            attention_mask=attention_mask, 
            labels=labels
        )

        return output.loss, output.logits


    def training_step(self, batch, batch_idx):

        input_ids = batch["inputs_ids"]
        attention_mask = batch["attention_mask"]
        labels= batch["targets"]
        loss, outputs = self(input_ids, attention_mask, labels)


        self.log("train_loss", loss, prog_bar=True, logger=True)

        return loss

    def validation_step(self, batch, batch_idx):
        input_ids = batch["inputs_ids"]
        attention_mask = batch["attention_mask"]
        labels= batch["targets"]
        loss, outputs = self(input_ids, attention_mask, labels)

        self.log("val_loss", loss, prog_bar=True, logger=True)

        return loss


    def configure_optimizers(self):
        return AdamW(self.parameters(), lr=0.0001)

模型训练

在训练转换器模型时,通常会批量迭代数据集,通过模型发送输入,并根据计算出的梯度和一组优化标准更改模型的参数。

def run():

    df_train, df_valid = train_test_split(
        df[0:10000], test_size=0.2, random_state=101
    )

    df_train = df_train.fillna("none")
    df_valid = df_valid.fillna("none")

    df_train['context'] = df_train['context'].apply(lambda x: " ".join(x.split()))
    df_valid['context'] = df_valid['context'].apply(lambda x: " ".join(x.split()))

    df_train['text'] = df_train['text'].apply(lambda x: " ".join(x.split()))
    df_valid['text'] = df_valid['text'].apply(lambda x: " ".join(x.split()))

    df_train['question'] = df_train['question'].apply(lambda x: " ".join(x.split()))
    df_valid['question'] = df_valid['question'].apply(lambda x: " ".join(x.split()))


    df_train = df_train.reset_index(drop=True)
    df_valid = df_valid.reset_index(drop=True)

    dataModule = T5DatasetModule(df_train, df_valid)
    dataModule.setup()

    device = DEVICE
    models = T5Model()
    models.to(device)

    checkpoint_callback  = ModelCheckpoint(
        dirpath="/kaggle/working",
        filename="best_checkpoint", 
        save_top_k=2,
        verbose=True,
        monitor="val_loss",
        mode="min"
    )

    trainer = pl.Trainer(
        callbacks = checkpoint_callback,
        max_epochs= EPOCHS,
        gpus=1,
        accelerator="gpu"
    )

    trainer.fit(models, dataModule)

run()

模型预测

要使用新输入对 T5 等微调的 NLP 模型进行预测,您可以按照以下步骤操作:

● 预处理新输入:对新输入文本进行标记化和预处理,以匹配应用于训练数据的预处理。确保它采用模型预期的正确格式。

● 使用微调模型进行推理: 加载您之前从检查点训练或加载的微调 T5 模型。

● 生成预测: 将预处理的新输入传递给模型进行预测。对于 T5,可以使用 generate 方法生成响应。

train_model = T5Model.load_from_checkpoint("/kaggle/working/best_checkpoint-v1.ckpt") 

train_model.freeze()

def generate_question(context, question):

    inputs_encoding =  tokenizer(
        context,
        question,
        add_special_tokens=True,
        max_length= INPUT_MAX_LEN,
        padding = 'max_length',
        truncation='only_first',
        return_attention_mask=True,
        return_tensors="pt"
        )


    generate_ids = train_model.model.generate(
        input_ids = inputs_encoding["input_ids"],
        attention_mask = inputs_encoding["attention_mask"],
        max_length = INPUT_MAX_LEN,
        num_beams = 4,
        num_return_sequences = 1,
        no_repeat_ngram_size=2,
        early_stopping=True,
        )

    preds = [
        tokenizer.decode(gen_id,
        skip_special_tokens=True, 
        clean_up_tokenization_spaces=True)
        for gen_id in generate_ids
    ]

    return "".join(preds)

预测

让我们使用带有新输入的微调 T5 模型生成预测:

*context = “对相似病例的分组进行聚类,例如,\可以找到相似的患者,或用于 *

*banking 字段中的客户细分。使用关联技术查找*

经常同时发生的项目或事件,例如,通常由特定客户一起购买的

杂货项目。使用异常检测来发现异常

和异常情况,例如信用卡欺诈检测。

que = “异常检测的例子是什么?”

print(generate_question(上下文, que))

context = "Classification is used when your target is categorical,\
 while regression is used when your target variable\
is continuous. Both classification and regression belong to the category \
of supervised machine learning algorithms."  


que = "When is classification used?"

print(generate_question(context, que))

结论

在本文中,我们开始了对自然语言处理 (NLP) 模型(特别是 T5 模型)进行微调的旅程,以完成问答任务。在整个过程中,我们深入研究了NLP模型开发和部署的各个方面。

关键要点:

● 探索了支撑其功能的编码器-解码器结构和自注意力机制。

● 超参数调优的艺术是优化模型性能的一项基本技能。

● 通过对学习率、批量大小和模型大小进行试验,我们可以有效地对模型进行微调。

● 精通标记化、填充以及将原始文本数据转换为适合模型输入的格式。

● 深入研究微调,包括加载预先训练的权重、修改模型层以及使其适应特定任务。

● 学习了如何清理和构建数据,将其拆分为训练集和验证集。

● 演示了它如何根据输入上下文和问题生成响应或答案,展示了其在现实世界中的效用。

常见问题解答

问题1. 什么是自然语言处理 (NLP) 中的微调?

答:NLP 中的微调涉及修改预训练模型的超参数和架构,以优化其针对特定任务或数据集的性能。

问题2. T5 等 NLP 模型中使用的 Transformer 架构是什么?

答:Transformer 架构是一种神经网络架构。它擅长处理顺序数据,是 T5 等模型的基础。它使用自注意力机制来理解上下文。

问题3. T5 等模型中的编码器-解码器结构的目的是什么?

答:在 NLP 中的序列到序列任务中,我们使用编码器-解码器结构。编码器处理输入数据,解码器生成输出数据。

问题4. 是否有可能在实际应用中利用 T5 等微调的 NLP 模型?

答:是的,您可以将微调模型应用于各种实际的 NLP 任务,包括文本生成、翻译和问答。

问题5. 如何开始微调 T5 等 NLP 模型?

答: 首先,您可以探索 Hugging Face 等库。这些库提供预先训练的模型和工具,用于微调数据集。学习 NLP 基础知识和深度学习概念也至关重要。


非常感谢大家的阅读,小Mo在这里祝你在末来的 Python 学习职业生涯中一切顺利!

后续小Mo会不定期更新书籍、视频等学习资源,以上这些书籍资料也可通过关注微信公众号免费获取哦!

欢迎关注我们的微信公众号:MomodelAl

同时,欢迎使用「Mo AI编程」微信小程序

以及登录官网,了解更多信息:Mo 人工智能教育实训平台

Mo,发现意外,创造可能

注:部分资源来源于互联网,若有侵权,请直接联系作者删除。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值