本文针对于huggingface使用.不是教程,只是我需要的东西.
调用bert类
参考博客:
1Huggingface简介及BERT代码浅析 - 知乎 (zhihu.com).
import torch from transformers import BertModel, BertTokenizer
这里我们调用bert-base模型,同时模型的词典经过小写处理
model_name = ‘bert-base-uncased’
读取模型对应的tokenizer
tokenizer = BertTokenizer.from_pretrained(model_name)
载入模型
model = BertModel.from_pretrained(model_name)
输入文本
input_text = “Here is some text to encode”
通过tokenizer把文本变成 token_id
input_ids = tokenizer.encode(input_text, add_special_tokens=True)
input_ids: [101, 2182, 2003, 2070, 3793, 2000, 4372, 16044, 102]
input_ids = torch.tensor([input_ids])
获得BERT模型最后一个隐层结果
with torch.no_grad(): last_hidden_states = model(input_ids)[0] # Models outputs are now tuples “”" shape: (1, 9, 768) “”"
上图就是如何使用bert嵌入文本.注意tokenization就是调用字典而已.经过model产生嵌入向量.
以bert为例子,看bertmodel类,它就是bert的主类.它的output是添加了objective任务的.而里边的bertembedding没有添加任务,只是嵌入而已.
作者说,BertEncoder主要将embedding的输出.是不是说bertencoder=bertembedding.
Bertpooler 其实就是将BERT的[CLS]的hidden_state 取出,经过一层DNN和Tanh计算后输出
class BertModel(BertPreTrainedModel): def init(self, config): super().init(config) self.config = config
self.embeddings = BertEmbeddings(config)
self.encoder = BertEncoder(config)
self.pooler = BertPooler(config)
self.init_weights()
下面这段话很重要
在这个文件中还有上述基础的BertModel的进一步的变化,比如BertForMaskedLM,BertForNextSentencePrediction这些是Bert加了预训练头的模型,还有BertForSequenceClassification, BertForQuestionAnswering 这些加上了特定任务头的模型。
这句话的意思是 头就是objective任务,上述第二行就是下游任务.
我们还是不了解上面话的含义,我们查阅huggingface的文档:BERT (huggingface.co).
hidden_size=768,就是bert嵌入的输出维度.
BertModel: 主类.
BertForPreTraing: 两个头,看来两个头就是两个任务.
BertForMaskedLM#
看了东于的博客:[BERT相关——(8)BERT-based Model代码分析 | 冬于的博客 (ifwind.github.io)](https://ifwind.github.io/2021/08/24/BERT相关——(8)BERT-based Model代码分析/#引言).
HuggingFace的transformers库中基于 BERT 的模型都是基于BertPreTrainedModel这一抽象基类的,而后者则基于一个更大的基类PreTrainedModel。这里我们关注BertPreTrainedModel的功能:BertPreTrainedModel用于初始化模型权重,同时维护继承自PreTrainedModel的一些标记身份或者加载模型时的类变量。
HuggingFace的transformers库提供了对两个目标都进行预训练、以及只对其中一个任务进行预训练的Bert预训练模型:
BertForPreTraining:进行MLM和NSP两个任务的预训练; BertForMaskedLM:只进行 MLM 任务的预训练; BertLMHeadModel:这个和上一个的区别在于,这一模型是作为 decoder 运行的版本;#这是什么意思?懂了,就是只能利用上文,不能利用下文. BertForNextSentencePrediction:只进行 NSP 任务的预训练。
注意,bert的两个任务都是分类任务.
BertForMaskedLM只完成MLM任务,事实上后续的RoBERTa、ALBERT、spanBERT等模型都移去了NSP任务(消除NSP损失在下游任务的性能上能够与原始BERT持平或略有提高)。
与上面的BertForMaskedLM模型不同,BertLMHeadModel模型是decoder版本,也就是只能利用上文而不能利用下文,任务修改为next token prediction。完成LM任务:注意这里做的是下一个token预测的任务
接下来介绍HuggingFace-Transformers库中实现的四种 Fine-tune 模型,基本都是分类任务,与上一篇博客相对应,不包括seq2seq模型。
one class-BertForSequenceClassification#句子分类 one class-BertForMultipleChoice class for each token-BertForTokenClassification#token分类 copy from input-BertForQuestionAnswering#输入为问题 +(对于 BERT 只能是一个)回答组成的句子对,输出为起始位置s和结束位置e用于标出回答中的具体文本。
什么是回归任务和分类任务?
简单来讲,分类任务 和 回归任务 的区别在于 需要预测的值的类型:
回归任务,是对 连续值 进行预测(比如 多少);#使用MSE 分类任务,是对 离散值 进行预测(比如 是不是,属不属于,或者 属于哪一类)。#使用交叉熵 比如,
预测 明天的气温是多少度,这是一个回归任务; 预测 明天会不会下雨,就是一个分类任务。
调用gpt类
参考:huggingface transformers预训练模型如何下载至本地,并使用? - 知乎 (zhihu.com).
特别注意三个类:使用的时候,非常简单。huggingface的transformers框架主要有三个类model类、configuration类、tokenizer类,这三个类,所有相关的类都衍生自这三个类,他们都有from_pretained()方法和save_pretrained()方法。
注意,from_pretained就可以微调了,save_pretrained就是存储自己的微调.
import torch from transformers import GPT2Tokenizer, GPT2LMHeadModel
从下载好的文件夹中加载tokenizer
这里你需要改为自己的实际文件夹路径
tokenizer = GPT2Tokenizer.from_pretrained(‘/dfsdata2/yucc1_data/models/huggingface/gpt2’) text = ‘Who was Jim Henson ? Jim Henson was a’
编码一段文本
编码后为[8241, 373, 5395, 367, 19069, 5633, 5395, 367, 19069, 373, 257]
indexed_tokens = tokenizer.encode(text)
转换为pytorch tensor
tensor([[ 8241, 373, 5395, 367, 19069, 5633, 5395, 367, 19069, 373, 257]])
shape为 torch.Size([1, 11])
tokens_tensor = torch.tensor([indexed_tokens])
从下载好的文件夹中加载预训练模型
model = GPT2LMHeadModel.from_pretrained(‘/dfsdata2/yucc1_data/models/huggingface/gpt2’)
设置为evaluation模式,去取消激活dropout等模块。
在huggingface/transformers框架中,默认就是eval模式
model.eval()
预测所有token
with torch.no_grad(): # 将输入tensor输入,就得到了模型的输出,非常简单 # outputs是一个元组,所有huggingface/transformers模型的输出都是元组 # 本初的元组有两个,第一个是预测得分(没经过softmax之前的,也叫作logits), # 第二个是past,里面的attention计算的key value值 # 此时我们需要的是第一个值 outputs = model(tokens_tensor) # predictions shape为 torch.Size([1, 11, 50257]), # 也就是11个词每个词的预测得分(没经过softmax之前的) # 也叫做logits predictions = outputs[0]
我们需要预测下一个单词,所以是使用predictions第一个batch,最后一个词的logits去计算
predicted_index = 582,通过计算最大得分的索引得到的
predicted_index = torch.argmax(predictions[0, -1, :]).item()
反向解码为我们需要的文本
predicted_text = tokenizer.decode(indexed_tokens + [predicted_index])
解码后的文本:‘Who was Jim Henson? Jim Henson was a man’
成功预测出单词 ‘man’
print(predicted_text)
欢迎留言讨论
|