语言模型GPT与HuggingFace应用

受到计算机视觉领域采用ImageNet对模型进行一次预训练,使得模型可以通过海量图像充分学习如何提取特征,然后再根据任务目标进行模型微调的范式影响,自然语言处理领域基于预训练语言模型的方法也逐渐成为主流。以ELMo为代表的动态词向量模型开启了语言模型预训练的大门,此后以GPT 和BERT为代表的基于Transformer 的大规模预训练语言模型的出现,使得自然语言处理全面进入了预训练微调范式新时代。

利用丰富的训练语料、自监督的预训练任务以及Transformer 等深度神经网络结构,预训练语言模型具备了通用且强大的自然语言表示能力,能够有效地学习到词汇、语法和语义信息。将预训练模型应用于下游任务时,不需要了解太多的任务细节,不需要设计特定的神经网络结构,只需要“微调”预训练模型,即使用具体任务的标注数据在预训练语言模型上进行监督训练,就可以取得显著的性能提升。

OpenAI 公司在2018 年提出的生成式预训练语言模型(Generative Pre-Training,GPT)是典型的生成式预训练语言模型之一。GPT 模型结构如图2.3所示,由多层Transformer 组成的单向语言模型,主要分为输入层,编码层和输出层三部分。
接下来我将重点介绍GPT 无监督预训练、有监督下游任务微调以及基于HuggingFace 的预训练语言模型实践。

一、 无监督预训练

GPT 采用生成式预训练方法,单向意味着模型只能从左到右或从右到左对文本序列建模,所采用的Transformer 结构和解码策略保证了输入文本每个位置只能依赖过去时刻的信息。
给定文本序列w = w1w2...wn,GPT 首先在输入层中将其映射为稠密的向量:

其中,

是词wi 的词向量,

 是词wi 的位置向量,vi 为第i 个位置的单词经过模型输入层(第0层)后的输出。GPT 模型的输入层与前文中介绍的神经网络语言模型的不同之处在于其需要添加

图1.1 GPT 预训练语言模型结构

位置向量,这是Transformer 结构自身无法感知位置导致的,因此需要来自输入层的额外位置信息。经过输入层编码,模型得到表示向量序列v = v1...vn,随后将v 送入模型编码层。编码层由L 个Transformer 模块组成,在自注意力机制的作用下,每一层的每个表示向量都会包含之前位置表示向量的信息,使每个表示向量都具备丰富的上下文信息,并且经过多层编码后,GPT 能得到每个单词层次化的组合式表示,其计算过程表示如下:

其中

 表示第L 层的表示向量序列,n 为序列长度,d 为模型隐藏层维度,L 为模型总层数。GPT 模型的输出层基于最后一层的表示h(L),预测每个位置上的条件概率,其计算过程可以表示为:

其中,

 为词向量矩阵,|V| 为词表大小。单向语言模型是按照阅读顺序输入文本序列w,用常规语言模型目标优化w 的最大似然估计,使之能根据输入历史序列对当前词能做出准确的预测:

其中θ 代表模型参数。也可以基于马尔可夫假设,只使用部分过去词进行训练。预训练时通常使用随机梯度下降法进行反向传播优化该负似然函数。

二、 有监督下游任务微调

通过无监督语言模型预训练,使得GPT 模型具备了一定的通用语义表示能力。下游任务微调(Downstream Task Fine-tuning)的目的是在通用语义表示基础上,根据下游任务的特性进行适配。下游任务通常需要利用有标注数据集进行训练,数据集合使用D 进行表示,每个样例由输入长度为n 的文本序列x = x1x2...xn 和对应的标签y 构成。
首先将文本序列x 输入GPT 模型,获得最后一层的最后一个词所对应的隐藏层输出h(L)n ,在此基础上通过全连接层变换结合Softmax 函数,得到标签预测结果。

其中

为全连接层参数,k 为标签个数。通过对整个标注数据集D 优化如下目标函数
精调下游任务:

下游任务在微调过程中,针对任务目标进行优化,很容易使得模型遗忘预训练阶段所学习到的通用语义知识表示,从而损失模型的通用性和泛化能力,造成灾难性遗忘(Catastrophic Forgetting)问题。因此,通常会采用混合预训练任务损失和下游微调损失的方法来缓解上述问题。在实际应用中,通常采用如下公式进行下游任务微调:

其中λ 取值为[0,1],用于调节预训练任务损失占比。

三、基于HuggingFace 的预训练语言模型实践

HuggingFace 是一个开源自然语言处理软件库。其的目标是通过提供一套全面的工具、库和模型,使得自然语言处理技术对开发人员和研究人员更加易于使用。HuggingFace 最著名的贡献之一是Transformer 库,基于此研究人员可以快速部署训练好的模型以及实现新的网络结构。除此之外,HuggingFace 还提供了Dataset 库,可以非常方便地下载自然语言处理研究中最常使用的基准数据集。本节中,将以构建BERT 模型为例,介绍基于Huggingface 的BERT 模型构建和使用方法。

3.1. 数据集合准备

常见的用于预训练语言模型的大规模数据集都可以在Dataset 库中直接下载并加载。例如,如果使用维基百科的英文语料集合,可以直接通过如下代码完成数据获取:

复制代码

from datasets import concatenate_datasets, load_dataset
bookcorpus = load_dataset("bookcorpus", split="train")
wiki = load_dataset("wikipedia", "20230601.en", split="train")
# 仅保留'text' 列
wiki = wiki.remove_columns([col for col in wiki.column_names if col != "text"])
dataset = concatenate_datasets([bookcorpus, wiki])
# 将数据集合切分为90% 用于训练,10% 用于测试
d = dataset.train_test_split(test_size=0.1)

接下来将训练和测试数据分别保存在本地文件中

def dataset_to_text(dataset, output_filename="data.txt"):
    """Utility function to save dataset text to disk,
    useful for using the texts to train the tokenizer
    (as the tokenizer accepts files)"""
    with open(output_filename, "w") as f:
        for t in dataset["text"]:
            print(t, file=f)
# save the training set to train.txt
dataset_to_text(d["train"], "train.txt")
# save the testing set to test.txt
dataset_to_text(d["test"], "test.txt")

3.2. 训练词元分析器(Tokenizer)

如前所述,BERT 采用了WordPiece 分词,根据训练语料中的词频决定是否将一个完整的词切分为多个词元。因此,需要首先训练词元分析器(Tokenizer)。可以使用transformers 库中的BertWordPieceTokenizer 类来完成任务,代码如下所示:

special_tokens = [
"[PAD]", "[UNK]", "[CLS]", "[SEP]", "[MASK]", "<S>", "<T>"
]#
if you want to train the tokenizer on both sets
# files = ["train.txt", "test.txt"]
# training the tokenizer on the training set
files = ["train.txt"]
# 30,522 vocab is BERT's default vocab size, feel free to tweak
vocab_size = 30_522
# maximum sequence length, lowering will result to faster training (when increasing batch size)
max_length = 512
# whether to truncate
truncate_longer_samples = False
# initialize the WordPiece tokenizer
tokenizer = BertWordPieceTokenizer()
# train the tokenizer
tokenizer.train(files=files, vocab_size=vocab_size, special_tokens=special_tokens)
# enable truncation up to the maximum 512 tokens
tokenizer.enable_truncation(max_length=max_length)
model_path = "pretrained-bert"
# make the directory if not already there
if not os.path.isdir(model_path):
    os.mkdir(model_path)
# save the tokenizer
tokenizer.save_model(model_path)
# dumping some of the tokenizer config to config file,
# including special tokens, whether to lower case and the maximum sequence length
with open(os.path.join(model_path, "config.json"), "w") as f:
    tokenizer_cfg = {
        "do_lower_case": True,
        "unk_token": "[UNK]",
        "sep_token": "[SEP]",
        "pad_token": "[PAD]",
        "cls_token": "[CLS]",
        "mask_token": "[MASK]",
        "model_max_length": max_length,
        "max_len": max_length,
    }
    json.dump(tokenizer_cfg, f)
# when the tokenizer is trained and configured, load it as BertTokenizerFast
tokenizer = BertTokenizerFast.from_pretrained(model_path)

3.3. 预处理语料集合

在启动整个模型训练之前,还需要将预训练语料根据训练好的Tokenizer 进行处理。如果文档长度超过512 个词元(Token),那么就直接进行截断。数据处理代码如下所示:

def encode_with_truncation(examples):
    """Mapping function to tokenize the sentences passed with truncation"""
    return tokenizer(examples["text"], truncation=True, padding="max_length",
        max_length=max_length, return_special_tokens_mask=True)
def encode_without_truncation(examples):
    """Mapping function to tokenize the sentences passed without truncation"""
    return tokenizer(examples["text"], return_special_tokens_mask=True)
# the encode function will depend on the truncate_longer_samples variable
encode = encode_with_truncation if truncate_longer_samples else encode_without_truncation
# tokenizing the train dataset
train_dataset = d["train"].map(encode, batched=True)
# tokenizing the testing dataset
test_dataset = d["test"].map(encode, batched=True)
if truncate_longer_samples:
    # remove other columns and set input_ids and attention_mask as PyTorch tensors

    train_dataset.set_format(type="torch", columns=["input_ids", "attention_mask"])
    test_dataset.set_format(type="torch", columns=["input_ids", "attention_mask"])
else:
    # remove other columns, and remain them as Python lists
    test_dataset.set_format(columns=["input_ids", "attention_mask", "special_tokens_mask"])
    train_dataset.set_format(columns=["input_ids", "attention_mask", "special_tokens_mask"])

truncate_longer_samples 布尔变量来控制用于对数据集进行词元处理的encode() 回调函数。如果设置为True,则会截断超过最大序列长度(max_length)的句子。否则,不会截断。如果设为truncate_longer_samples 为False,需要将没有截断的样本连接起来,并组合成固定长度的向量。

3.4. 模型训练

在构建了处理好的预训练语料之后,就可以开始模型训练。代码如下所示:

# initialize the model with the config
model_config = BertConfig(vocab_size=vocab_size, max_position_embeddings=max_length)
model = BertForMaskedLM(config=model_config)
# initialize the data collator, randomly masking 20% (default is 15%) of the tokens
# for the Masked Language Modeling (MLM) task
data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer, mlm=True, mlm_probability=0.2
)
training_args = TrainingArguments(
    output_dir=model_path, # output directory to where save model checkpoint
    evaluation_strategy="steps", # evaluate each `logging_steps` steps
    overwrite_output_dir=True,
    num_train_epochs=10, # number of training epochs, feel free to tweak
    per_device_train_batch_size=10, # the training batch size, put it as high as your GPU memory fits
    gradient_accumulation_steps=8, # accumulating the gradients before updating the weights
    per_device_eval_batch_size=64, # evaluation batch size
    logging_steps=1000, # evaluate, log and save model checkpoints every 1000 step
    save_steps=1000,
    # load_best_model_at_end=True, # whether to load the best model (in terms of loss)
    # at the end of training
    # save_total_limit=3, # whether you don't have much space so you
    # let only 3 model weights saved in the disk
)
trainer = Trainer(
    model=model,
    args=training_args,
    data_collator=data_collator,
    train_dataset=train_dataset,
    eval_dataset=test_dataset,
)
# train the model
trainer.train()

开始训练后,可以如下输出结果:

[10135/79670 18:53:08 < 129:35:53, 0.15 it/s, Epoch 1.27/10]
Step Training Loss Validation Loss
1000 6.904000 6.558231
2000 6.498800 6.401168
3000 6.362600 6.277831
4000 6.251000 6.172856
5000 6.155800 6.071129
6000 6.052800 5.942584
7000 5.834900 5.546123
8000 5.537200 5.248503
9000 5.272700 4.934949
10000 4.915900 4.549236

3.5. 模型使用

基于训练好的模型,可以针对不同应用需求进行使用。

# load the model checkpoint
model = BertForMaskedLM.from_pretrained(os.path.join(model_path, "checkpoint-10000"))
# load the tokenizer
tokenizer = BertTokenizerFast.from_pretrained(model_path)
fill_mask = pipeline("fill-mask", model=model, tokenizer=tokenizer)
# perform predictions
examples = [
"Today's most trending hashtags on [MASK] is Donald Trump",
"The [MASK] was cloudy yesterday, but today it's rainy.",
]
for example in examples:
    for prediction in fill_mask(example):
        print(f"{prediction['sequence']}, confidence: {prediction['score']}")
    print("="*50)

可以得到如下输出:

today's most trending hashtags on twitter is donald trump, confidence: 0.1027069091796875
today's most trending hashtags on monday is donald trump, confidence: 0.09271949529647827
today's most trending hashtags on tuesday is donald trump, confidence: 0.08099588006734848
today's most trending hashtags on facebook is donald trump, confidence: 0.04266013577580452
today's most trending hashtags on wednesday is donald trump, confidence: 0.04120611026883125
==================================================
the weather was cloudy yesterday, but today it's rainy., confidence: 0.04445931687951088
the day was cloudy yesterday, but today it's rainy., confidence: 0.037249673157930374
the morning was cloudy yesterday, but today it's rainy., confidence: 0.023775646463036537
the weekend was cloudy yesterday, but today it's rainy., confidence: 0.022554103285074234
the storm was cloudy yesterday, but today it's rainy., confidence: 0.019406016916036606
==================================================

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/232485.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

创建dockerSwarm nfs挂载

创建dockerSwarm nfs挂载 nfs高可用部署(lsyncd两主机双向同步) nfs高可用部署(lsyncd三主机三向同步) 1. 通过 Volume 1.1 创建 Docker Volume 每个 swarm 节点均创建相同名称的 Docker Volume&#xff08;名称为 nfs120&#xff09; docker volume create --driver local …

Jupyter notebook修改背景主题

打开Anaconda Prompt&#xff0c;输入以下内容 1. pip install --upgrade jupyterthemes 下载对应背景主题包 出现Successfully installed jupyterthemes-0.20.0 lesscpy-0.15.1时&#xff0c;说明已经下载安装完成 2. jt -l 查看背景主题列表 3. jt -t 主题名称&#xff08;…

【docker 】centOS 安装docker

官网 docker官网 github源码 卸载旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 安装软件包 yum install -y yum-utils \device-mapper-persistent-data…

Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)

目录 一、前言 二、Bean配置信息重用 1.简介 : 2.实例 : 三、关于Bean的创建顺序 1.简介 : 2.实例 : 四、关于Bean的单例和多例 1.简介 : 2.实例 : 五、关于Bean的生命周期 1.简介 : 2.实例 : 六、Bean配置后置处理器 1.简介 : 2.实例 : 七、通过.properties文…

AcWing 93. 递归实现组合型枚举

Every day a AcWing 题目来源&#xff1a;93. 递归实现组合型枚举 解法1&#xff1a;回溯算法 标准的回溯算法模板题。 如果把 n、m 和数组 nums 都设置成全局变量的话&#xff0c;backtracking 回溯函数可以只用一个参数 level。 注意传参时 nums 不能用引用&#xff0c;…

Hive SQL间隔连续问题

问题引入 下面是某游戏公司记录的用户每日登录数据, 计算每个用户最大的连续登录天数&#xff0c;定义连续登录时可以间隔一天。举例&#xff1a;如果一个用户在 1,3,5,6,9 登录了游戏&#xff0c;则视为连续 6 天登录。 id dt1001 2021-12-121002 2021-12-12…

SQL语句---删除索引

介绍 使用sql语句删除索引。由于索引会占用一定的磁盘空间&#xff0c;因此&#xff0c;为了避免影响数据库性能&#xff0c;应该及时删除不再使用的索引。 命令 drop index 索引名 on 表名;例子 删除a表中的singleidx索引&#xff1a; drop index singleidx on a;下面是执…

GoldWave注册机 最新中文汉化破解版-安装使用教程

GoldWave是一个功能强大的数字音乐编辑器&#xff0c;是一个集声音编辑、播放、录制和转换的音频工具。它还可以对音频内容进行转换格式等处理。它体积小巧&#xff0c;功能却无比强大&#xff0c;支持许多格式的音频文件&#xff0c;包括WAV、OGG、VOC、 IFF、AIFF、 AIFC、AU…

FPGA 低延时 TCP UDP IP协议栈兼容1G 10G 25G MAC

在计算和数据中心、军事和航天、政府、仪器与测量、金融服务和广播和视频等行业&#xff0c;需要高可靠性的硬件和软件产品&#xff0c;帮助客户更快地开发部署新一代产品&#xff0c;减少技术和市场风险&#xff0c;我司研发的低延迟TCP/IP的IP核的传输速率高于传统网口&#…

汽车4S店中的“S”指的什么?柯桥生活英语学习

很多人买车都会去4S店选购 因为比较有保障 服务又很到位 可你有没有想过 这里的“4S”是什么意思 其实&#xff0c;这几个单词大家都认识 今天我们就来聊一下 与“4S店”相关的英文表达 01 “4S店”的英语表达 其实&#xff0c;4S店的全称是&#xff1a;汽车销售服务4S店…

基于Java的汽车客运站管理系统的设计与实现论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对汽车客运站售票信息管理混乱&#xff0c;出错率高&#xff0c;信息安…

Redis对象类型检测与命令多态

一. 命令类型 Redis中操作键的命令可以分为两类。 一种命令可以对任意类型的键执行&#xff0c;比如说DEL&#xff0c;EXPIRE&#xff0c;RENAME&#xff0c;TYPE&#xff0c;OBJECT命令等。 举个例子&#xff1a; #字符串键 127.0.0.1:6379> set msg "hello world&…

Verilog基础:寄存器输出的两种风格

相关文章 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 Verilog中的寄存器操作一般指的是那些对时钟沿敏感而且使用非阻塞赋值的操作。例如状态机中的状态转移&#xff0c;实际上就是一种寄存器操作&#xff0c;因为这相…

换根DP模板

给你一个无根树&#xff0c;问你以哪个节点为根节点的时候得到所有点的深度之和最大 《贴一张 知乎大佬的一个解释》 #include<bits/stdc.h> using namespace std; const int N 2e610; using ll long long; ll dep[N],sz[N]; ll ans[N]; vector<int>g[N]; int n;…

What the DAAM: Interpreting Stable Diffusion Using Cross Attention

What the DAAM: Interpreting Stable Diffusion Using Cross Attention (Paper reading) Raphael Tang, Comcast Applied AI, ACL2023 best paper, Code, Paper 1. 前言 大规模扩散神经网络是文本到图像生成中的一个重要里程碑&#xff0c;但人们对其了解甚少&#xff0c;缺…

超详细的Selenium:设置元素等待、上传文件、下载文件

前言&#xff1a;在工作和学习selenium自动化过程中记录学习知识点&#xff0c;深化知识点 1、设置元素等待 元素定位之元素等待-- WebDriver提供了两种类型的等待&#xff1a;显示等待和隐式等待。 同时&#xff0c;在这我为大家准备了一份软件测试视频教程&#xff08;含…

基于CentOS7环境搭建Graylog日志系统

我配置的Graylog是4版本的&#xff0c;因为更高级的版本没有针对centos CentOS installationhttps://go2docs.graylog.org/4-x/downloading_and_installing_graylog/centos_installation.html 官方文档挺详细&#xff0c;但有的地方可能会出问题 1. 安装MongoDB Inst…

代码随想录二刷 |二叉树 |在每个树行中找最大值

代码随想录二刷 &#xff5c;二叉树 &#xff5c;在每个树行中找最大值 题目描述解题思路代码实现 题目描述 515.在每个树行中找最大值 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 示例1&#xff1a; 输入: root [1,3,2,5,3,null,9] 输出…

Spring基于XML文件配置AOP

AOP AOP&#xff0c;面向切面编程&#xff0c;是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象&#xff0c;一个对象包括静态的属性信息&#xff0c;包括动态的方法信息等。而AOP是横向的对不同事物的抽象&#xff0c;属性与属性、方法与方法、对象与对象都可以组成一个…

nginx多端口部署

1.配置nginx.conf文件 有几个端口需要部署就写几个server&#xff0c;我这里只部署了两个端口分别为80和81端口&#xff0c;所以有两个server文件。80端口项目入口在根目录的test文件中&#xff0c;81端口项目入口在根目录的test1文件夹中。 2.准备项目文件html文件 在/test1…