HuggingFace API学习
transformers.pipline
pipline(“model name”)
可选的pipline:
Zero-shot classification:
可以自定义分类标签,预训练模型会将判断该句子是否属于这些自定义标签。
NER(named entity recognition)命名实体识别
ner = pipeline("ner", grouped_entities=True)
问答任务
question_answer = pipeline("question-answering")
result = question_answer(
question="Where do I work?",
context="My name is Sylvain and I work at Hugging Face in Brooklyn",
)
总结任务(Summarization)
summarizer = pipeline("summarization")
不同类型的Transformer模型
- GPT-like(regressive Transformer models)自回归Transformer模型
- BERT-like(auto-encoding Transformer models)自编码Transformer模型
- BART/T5-like(seq2seq Transformer models)序列到序列Transformer模型
编码器:适用于需要理解输入的任务,例如句子分类和命名实体识别。
解码器:适用于文本生成等生成任务
编码器-解码器或者序列到序列模型:适用于需要输入的生成任务,例如翻译和摘要。
在每个阶段,注意力层都可以访问初始句子中的所有单词。这些模型被描述为具有“双向注意力”,通常为成为auto-encoding model(自动编码模型)
Encoder models最适用于需要理解整个句子的任务。例如分类,命名实体识别,问答。该系列模型的代表有:ALBERT、BERT、DistilBERT、ELECTRA、RoBERTa
Decoder models使用Transformer模型中的解码器。在每个阶段,注意力层只能访问句子中位于它之前的单词,这些模型通常被成为auto-regressive models(自回归模型)这些模型适用于文本生成,该系列模型的代表有CTRL、GPT、GPT-2、Transformer XL
Encoder-Decoder models就是seq2seq模型。编码器可以访问输入的所有单词,解码器只能访问输入中给定单词之前的单词。seq2seq模型最适合围绕根据给定输入生成新句子的任务,例如摘要、翻译或生成式问答。该系列模型的代表有:BART、mBART、Marian、T5
Behind the pipeline
在使用pipeline方法时,底层都发生了什么事情?
-
使用tokenizer(分词器)进行预处理
from transformers import AutoTokenizer checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" tokenizer = AutoTokenizer.from_pretrained(checkpoint)
处理过后,字符串转化为了ids,并存放在result中的input_ids中。
可以直接使tokenizer返回tensor类型,并且可以指定是什么机器学习框架中的tensor
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
-
相同的方法得到model
from transformers import AutoModel checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" model = AutoModel.from_pretrained(checkpoint)
该模型使用的是Transformer的Encoder,输出结果的维度是[batch size, Seq len, Hidden size]
除了得到隐藏层的“Model”,还有很多其他的语言模型:
-
Mode的输出实际上是隐藏层,隐藏层将会被输入到一个叫“head”的层做处理(个人理解这个heda层有点像是下游任务模型)
例如使用句子分类的模型:
from transformers import AutoModelForSequenceClassification checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" model = AutoModelForSequenceClassification.from_pretrained(checkpoint) outputs = model(**inputs)
-
输出之后的处理
一般是softmax
Model
创建一个Transformer模型:
from transformers import BertConfig, BertModel
# Building the config
config = BertConfig()
# Building the model from the config
model = BertModel(config)
Config类拥有很多可以用于创建模型的配置信息:
BertConfig {
[...]
"hidden_size": 768,
"intermediate_size": 3072,
"max_position_embeddings": 512,
"num_attention_heads": 12,
"num_hidden_layers": 12,
[...]
}
这种创建方法,该模型的参数是随机初始化的。
使用一下方法导入预训练的模型:
from transformers import BertModel
model = BertModel.from_pretrained("bert-base-cased")
可以初始化Bert模型的chechpoint的完整列表:
https://huggingface.co/models?filter=bert
模型的保存方法:
model.save_pretrained( "directory_on_my_computer" )
Tokenizers
一句话–>数字
-
word-based:基于词的
一种语言的词汇太多,使用词表覆盖所有是不可能的,因此就有了[UNK],要尽可能的少引用这个token。一种减少引用[UNK]的方法是,使用一个character-based的分词器。
-
character-based:有两个优点
- 词表小很多
- 少得多的[UNK]
出现了标点符号问题,而且英文中这样分词意义不大,但是中文中每个字能包含更多的信息。而且一个词语可能包含多个基于字符的标记。
为了两全其美,有了第三种技术:子词标记化
-
subword tokenization
频繁的单词不应该被划分为更小的单词,但是不频繁的应该被拆分为有意义的子词。
加载和保存:和Model一样
text–>encoding:需要两步
- 分词
- 转化为IDs
Handling multiple sequences
一次处理1个序列,由于模型需要的输入默认是有batch的,解决方法是:
input_ids = torch.tensor([ids])
如果一次处理多个序列,则怎么解决长度不同的问题?
Padding the inputs:
batched_ids = [
[200, 200, 200],
[200, 200]
]
转换为:
padding_id = 100
batched_ids = [
[200, 200, 200],
[200, 200, padding_id],
]
但是有一个问题,由于自注意力机制,padding_id会对整个seq造成影响,为了取消这种影响,可以使用Attention masks
Attention masks
Attention mask使用0,1标记,1代表注意力层不应该忽略,0表示注意力层应该忽略。
batched_ids = [
[200, 200, 200],
[200, 200, tokenizer.pad_token_id],
]
attention_mask = [
[1, 1, 1],
[1, 1, 0],
]
outputs = model(torch.tensor(batched_ids), attention_mask=torch.tensor(attention_mask))
print(outputs.logits)
Longer Seqence
transformer模型对输入的模型序列长度有限制,如果要求处理更长序列怎么办?两种方法:
-
使用支持序列长度更长的模型:
Longformer、LED
-
截断序列
sequence = sequence[:max_sequence_length]
Putting it all together
tokenizer的强大:
padding:
# Will pad the sequences up to the maximum sequence length
model_inputs = tokenizer(sequences, padding="longest")
# Will pad the sequences up to the model max length
# (512 for BERT or DistilBERT)
model_inputs = tokenizer(sequences, padding="max_length")
# Will pad the sequences up to the specified max length
model_inputs = tokenizer(sequences, padding="max_length", max_length=8)
截断:
model_inputs = tokenizer(sequences, max_length=8, truncation=True)
注意:先分词再转化为id的输出和直接调用tonkenizer的输出不同,因为后者还对原来的句子加上了[CLS]和[SEP]的token
总体使用:
tokens = tokenizer(sequences, padding=True, truncation=True, return_tensors="pt")
output = model(**tokens)