Huggingface T5模型代码笔记

2023-12-24 19:04

本文主要是介绍Huggingface T5模型代码笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0 前言

本博客主要记录如何使用T5模型在自己的Seq2seq模型上进行Fine-tune。

1 文档介绍

本文档介绍来源于Huggingface官方文档,参考T5。

1.1 概述

T5模型是由Colin Raffel, Noam Shazeer, Adam Roberts, Katherine Lee, Sharan Narang, Michael Matena, Yanqi Zhou, Wei Li, Peter J. Liu.在论文 Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer中提出的。

该论文摘要如下:

迁移学习在自然语言处理(NLP)中已经成为一种强大的技术。迁移学习是指,模型首先在数据丰富的任务上进行预训练,然后再对下游任务进行微调。迁移学习的有效性引起了不同的方法、方法和实践。在本文中,我们通过引入一个统一的框架,将每个语言问题转换成文本到文本的格式,来探索自然语言处理的迁移学习技术。我们的系统研究比较了数十项语言理解任务的训练前目标、架构、未标记数据集、迁移方法和其他因素。通过将我们的探索与规模和我们的新“Colossal Clean Crawled Corpus”相结合,我们在总结、问答、文本分类等许多基准测试中取得了最先进的结果。为了促进NLP迁移学习的未来工作,我们发布了我们的数据集、预训练模型和代码。

提示:

  • T5是一种编码器-解码器模型,在非常多的无监督和有监督任务上进行多任务训练,并将每个任务转换为文本到文本格式。T5可以很好地处理各种任务,通过在每个任务对应的输入前加上不同的前缀,例如:translate English to German: …,摘要:summarize: ….(注:这里是指输入的文本可以通过加入特定前缀的方式指定是那种text-to-text任务,比如你想让T5做翻译任务,那么给他的输入就可以是"translate English to German: What is your name?")。关于使用哪个前缀的更多信息,原论文的附录D给出了所有的前缀。对于序列到序列的生成,建议使用generate()函数。这种方法负责通过cross-attention层将编码输入到解码器,并自动回归生成解码器输出。T5使用相对标量嵌入。编码器输入填充可以在左边和右边完成。

1.2 训练

T5是一个编码器-解码器模型,并将所有NLP问题转换为文本到文本的形式。它是通过teacher forcing(如果不熟悉,可以参考What is Teacher Forcing for Recurrent Neural Networks?)的方式进行训练的。这意味着对于训练,我们总是需要一个输入序列和一个目标序列。输入序列通过input_ids喂给模型的Encoder。目标序列在其右边,即跟在一个start-sequence token之后,通过decoder_input_ids喂给模型的Decoder。通过teacher forcing的方式,目标序列最后会加一个EOS token(表示结束End Of Sentence),并作为标签。T5可以在监督和非监督的方式下进行训练/微调。

1.2.1 无监督去噪训练

在该设置下,输入序列的范围被所谓的哨点标记(sentinel tokens,也就是唯一的掩码标记)屏蔽,而输出序列则由相同的哨点标记和真实掩码标记的串联组成。每个哨兵标记代表这个句子的唯一掩码标记,应该从<extra_id_0>, <extra_id_1>, … 直到<extra_id_99>。默认情况下,T5 Tokenizer中有100个sentinel token可用。

例如,句子"the cute dog walks in the park" 中掩盖"cute dog"和"the"应按如下方式处理:

from transformers import T5ForConditionalGeneration, T5Tokenizer
model = T5ForConditionalGeneration.from_pretrained("t5-small")
tokenizer = T5Tokenizer.from_pretrained("t5-small")input_ids = tokenizer('The <extra_id_0> walks in <extra_id_1> park', return_tensors='pt').input_ids
labels = tokenizer('<extra_id_0> cute dog <extra_id_1> the <extra_id_2>', return_tensors='pt').input_ids
# the forward function automatically creates the correct decoder_input_ids
loss = model(input_ids=input_ids, labels=labels).loss

1.2.2 有监督训练

在该设置下,输入序列和输出序列是标准的序列到序列的输入输出映射。在翻译中,例如输入序列"the house is wonderful.“和输出序列"Das Haus ist wunderbar”,这些句子应按下列方法处理:

from transformers import T5ForConditionalGeneration, T5Tokenizer
model = T5ForConditionalGeneration.from_pretrained("t5-small")
tokenizer = T5Tokenizer.from_pretrained("t5-small")input_ids = tokenizer('translate English to German: The house is wonderful.', return_tensors='pt').input_ids
labels = tokenizer('Das Haus ist wunderbar.', return_tensors='pt').input_ids
# the forward function automatically creates the correct decoder_input_ids
loss = model(input_ids=input_ids, labels=labels).loss

Tokenizer中的return_tensors的作用
若设置return_tensors=“pt”,则返回为tensor,否则为正常list。

inputs = tokenizer("translate English to Spanish: Find all student's name in students table.")
print(inputs)
{'input_ids': [13959, 1566, 12, 5093, 10, 2588, 66, 1236, 31, 7, 564, 16, 481, 953, 5, 1], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
inputs = tokenizer("translate English to Spanish: Find all student's name in students table.", return_tensors="pt")
print(inputs)
{'input_ids': tensor([[13959,  1566,    12,  5093,    10,  2588,    66,  1236,    31,     7,564,    16,   481,   953,     5,     1]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}

2 一个简单T5翻译示例

以下内容涉及一些Pytorch搭建神经网络模型的基础知识,不了解的朋友可以参考这个系列:莫凡Pytorch学习笔记(一)

2.1 模型搭建

我们借助T5ForConditionalGeneration模型来搭建一个简单的由文本到SQL语句的翻译模型。其Pytorch实现如下:

class T5ForTextToSQL(torch.nn.Module):'''A basic T5 model for Text-to-SQL task.'''def __init__(self):super(T5ForTextToSQL, self).__init__()self.t5 = T5ForConditionalGeneration.from_pretrained('t5-small')def forward(self, input_ids, labels):out = self.t5(input_ids=input_ids, labels=labels)return outdef generate(self, input_ids):result = self.t5.generate(input_ids=input_ids)return result

该类共三个方法。其中__init__和forward方法是必须要实现的。这里的generate也是原模型的方法,我们用于验证。

注意::这个类其实就是一个非常简单的T5ForConditionalGeneration类,但是我们这里把它封装为一个自己的类的目的主要有以下几点:

  1. 方便后续拓展,例如增加一些自定义的模块
  2. 仅保留T5ForConditionalGeneration的forward和generate函数给用户使用

2.2 数据集

这里我们使用一个自定义的数据集来快速开始。其定义如下:

class TextToSQL_Dataset(torch.utils.data.Dataset):'''A simple text-to-sql dataset example.'''def __init__(self, text_l, schema_l, sql_l, tokenizer, block_size=1):self.tokenizer = tokenizerself.max_len = block_sizeself.text = text_lself.scheme = schema_lself.sql = sql_ldef _text_to_encoding(self, item):return self.tokenizer(item)def _text_to_item(self, text):try:if (text is not None):return self._text_to_encoding(text)else:return Noneexcept:return Nonedef __len__(self):return len(self.sql)def __getitem__(self, _id):text = self.text[_id]sql = self.sql[_id]schema = self.scheme[_id]text_encodings = self._text_to_item("translate Text to SQL: " + text)sql_encodings = self._text_to_item(sql)schema_encodings = self._text_to_item(schema)item = dict()item['text_encodings'] = {key: torch.tensor(value) for key, value in text_encodings.items()}item['sql_encodings'] = {key: torch.tensor(value) for key, value in sql_encodings.items()}item['schema_encodings'] = {key: torch.tensor(value) for key, value in schema_encodings.items()}return item

我们的主要目的是跑通整个Fine-tune T5到Text-to-SQL任务上,所以为了不浪费更多的时间在构建数据集上面,这里我自已编写了一些自然语言文本到SQL语句的对应,用来快速开始。

其中,训练集和测试集如下:

# 以下为train_settext_l = ["Find all student names in student database.","Count student's number for class 1. ","Given the max student age in class 1.","Please find the minium student age in class 1.","Tell me the number of classes.","Who is the student that older than 15."
]
schema_l = ['Table: student$$header: name%%age%%class%%',
]*len(text_l)
sql_l = ["SELECT name FROM student","SELECT COUNT(*) FROM student WHERE class=1","SELECT MAX(age) FROM student WHERE class=1","SELECT MIN(age) FROM student WHERE class=1","SELECT COUNT(class) FROM student","SELECT name FROM student WHERE age>15",
]# 以下为test_set
test_text_l = ["Find all student ages in student database.","Count student's number for class 3. ","Given the min student age in class 2.","Please find the maxium student age in class 2.","Who is the student that younger than 14."
]
test_schema_l = ['Table: student$$header: name%%age%%class%%',
]*len(text_l)
test_sql_l = ["SELECT age FROM student","SELECT COUNT(*) FROM student WHERE class=3","SELECT MIN(age) FROM student WHERE class=2","SELECT MAX(age) FROM student WHERE class=2","SELECT name FROM student WHERE age<14",
]

这里的几个文本-SQL语句对都比较简单,只是为了用于测试流程完整性。

在构建好数据集文本后,我们定义和生成dataset以及dataloader对象:

train_dataset = TextToSQL_Dataset(text_l, schema_l, sql_l, tokenizer)
test_dataset = TextToSQL_Dataset(test_text_l, test_schema_l, test_sql_l, tokenizer)
train_loader = DataLoader(train_dataset, batch_size=1, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1, shuffle=True)

2.3 模型初始化

首先,初始化一个简单的模型:

model = T5ForTextToSQL()

为了验证训练的有效性,我们先来看看一个最初的不经过Fine-tune的原始T5模型在Text-to-SQL任务上的表现。

这里我们直接使用测试集进行评估测试,主要代码就是调用其generate函数来生成输出的Sequence并与ground truth进行对比。

device = torch.device('cuda:3') if torch.cuda.is_available() else torch.device('cpu')
model.eval()
model = model.to(device)
for i,batch in enumerate(test_loader):input_ids = batch['text_encodings']['input_ids'].to(device)sql_ids = batch['sql_encodings']['input_ids'].to(device)result = model.generate(input_ids)print("==="*20)print("Question:")print(tokenizer.decode(input_ids[0]))print("SQL:")print(tokenizer.decode(result[0]))print()

运行以上代码,得到输出如下:

============================================================
Question:
translate Text to SQL: Who is the student that younger than 14.</s>
SQL:
<pad> Text zu SQL: Wer ist der Student, der unter 14 Jahren ist?</s>============================================================
Question:
translate Text to SQL: Find all student ages in student database.</s>
SQL:
<pad> Text in SQL: Finden Sie alle Studenten Alter in der Studentendatenbank.</s>============================================================
Question:
translate Text to SQL: Given the min student age in class 2.</s>
SQL:
<pad> Text zu SQL: Angesichts des min Studenten Alters in der Klasse 2============================================================
Question:
translate Text to SQL: Count student's number for class 3.</s>
SQL:
<pad> Text in SQL: Count student's number for class 3.</s>============================================================
Question:
translate Text to SQL: Please find the maxium student age in class 2.</s>
SQL:
<pad> Text in SQL: Bitte finden Sie das maxium Studentenalter in der Klasse

可以看到,此时模型的输出,比如”Text zu SQL: Wer ist der Student, der unter 14 Jahren ist?“或”Text in SQL: Bitte finden Sie das maxium Studentenalter in der Klasse“好像是一些英语翻译成德语/法语的结果输入,并不能够输出SQL语句(无论是形式和内容,一点儿都不像)。

接下来,我们对这个简单的模型进行训练。

2.4 模型的训练

在进行模型训练时,我们首先要设置好优化器。这里我们采用T5在预训练时使用的AdamW又优化器,学习率设置为5e-5(这些超参数后面都可以仔细精调)。

optim = AdamW(model.parameters(), lr=5e-5)device = torch.device('cuda:3') if torch.cuda.is_available() else torch.device('cpu')
model.train()
model = model.to(device)for epoch in range(100):for i,batch in enumerate(train_loader):optim.zero_grad()input_ids = batch['text_encodings']['input_ids'].to(device)sql_ids = batch['sql_encodings']['input_ids'].to(device)loss = model(input_ids=input_ids, labels=sql_ids).lossloss.backward()optim.step()if epoch % 10 == 0 and i % 10 == 0:print("Epoch: ", epoch, " , step: ", i)print("training loss: ", loss.item())

运行以上代码,程序的输出如下:

Epoch:  0  , step:  0
training loss:  5.786584854125977
Epoch:  10  , step:  0
training loss:  3.1280531883239746
Epoch:  20  , step:  0
training loss:  1.795115351676941
Epoch:  30  , step:  0
training loss:  0.7517924308776855
Epoch:  40  , step:  0
training loss:  0.2508695125579834
Epoch:  50  , step:  0
training loss:  0.0881464034318924
Epoch:  60  , step:  0
training loss:  0.3708261251449585
Epoch:  70  , step:  0
training loss:  0.0828586220741272
Epoch:  80  , step:  0
training loss:  0.03668573126196861
Epoch:  90  , step:  0
training loss:  0.02559477463364601

可以看到,随着模型训练的进行,loss降低到一个比较低的水平后基本收敛。接下来,我们来验证一下模型是否真正学到了东西。

2.5 模型的评估

我们手动查看模型在测试集上的表现效果,并与2.3中的模型输出进行对比。

device = torch.device('cuda:3') if torch.cuda.is_available() else torch.device('cpu')
model.eval()
model = model.to(device)
for i,batch in enumerate(test_loader):input_ids = batch['text_encodings']['input_ids'].to(device)sql_ids = batch['sql_encodings']['input_ids'].to(device)result = model.generate(input_ids)print("==="*20)print("Question:")print(tokenizer.decode(input_ids[0]))print("SQL:")print(tokenizer.decode(result[0]))print()

运行以上代码,其输出如下:

============================================================
Question:
translate Text to SQL: Given the min student age in class 2.</s>
SQL:
<pad> SELECT MAX(age) FROM student WHERE class=2</s>============================================================
Question:
translate Text to SQL: Who is the student that younger than 14.</s>
SQL:
<pad> SELECT name FROM student WHERE age>14</s>============================================================
Question:
translate Text to SQL: Find all student ages in student database.</s>
SQL:
<pad> SELECT MIN(age) FROM student</s>============================================================
Question:
translate Text to SQL: Please find the maxium student age in class 2.</s>
SQL:
<pad> SELECT MAX(age) FROM student WHERE class=2</s>============================================================
Question:
translate Text to SQL: Count student's number for class 3.</s>
SQL:
<pad> SELECT COUNT(*) FROM student WHERE class=3</s>

可以看到,相比于最开始的2.3中的模型输出,此时的输出已经是一个简单的SQL语句形式了,而且对于问题4

  • ”translate Text to SQL: Please find the maxium student age in class 2.“

模型的生成语句

  • ”SELECT MAX(age) FROM student WHERE class=2“
    完全正确。
    同样的,对于问题5
  • ”translate Text to SQL: Count student’s number for class 3.“,

模型的生成语句

  • ”SELECT COUNT(*) FROM student WHERE class=3“。
    也完全正确。

从上述结果分析来看,这样简单的模型已经能够对某些简单的自然语言问句给出正确的SQL语句回答了(当然,主要是我们的测试集太简单,这里也仅做示例而已)。

后续我们其实可以考虑扩展我们的模型以适应不同的应用场景。

这篇关于Huggingface T5模型代码笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/532811

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学