huggingface使用
https://github.com/huggingface/transformers
https://github.com/tal-tech/edu-bert
李理 Huggingface Transformer教程(一)
Tokenizer:https://huggingface.co/docs/transformers/tokenizer_summary
用huggingface调用好未来预训练模型
1 | from transformers import AutoTokenizer |
模型文件夹要放:
- 配置文件,config.json
- 词典文件,vocab.txt
- 预训练模型文件,pytorch_model.bin
- 额外的文件,tokenizer_config.json、special_tokens_map.json,这是tokenizer需要使用的文件,如果出现的话,也需要保存下来。没有的话,就不必在意。
huggingface的transformers框架主要有三个类model类、configuration类、tokenizer类,这三个类,所有相关的类都衍生自这三个类,他们都有from_pretained()方法和save_pretrained()方法。
from_pretrained方法的第一个参数都是pretrained_model_name_or_path,这个参数设置为我们下载的文件目录即可。
用huggingface调用model hub的预训练模型
1 | classifier = pipeline('sentiment-analysis', model="nlptown/bert-base-multilingual-uncased-sentiment") |
除了通过名字来制定model参数,我们也可以传给model一个包含模型的目录的路径,也可以传递一个模型对象。如果我们想传递模型对象,那么也需要传入tokenizer。
我们需要两个类,一个是AutoTokenizer,我们将使用它来下载和加载与模型匹配的Tokenizer。另一个是AutoModelForSequenceClassification(如果用TensorFlow则是TFAutoModelForSequenceClassification)。注意:模型类是与任务相关的,我们这里是情感分类的分类任务,所以是AutoModelForSequenceClassification。
1 | from transformers import AutoTokenizer, AutoModelForSequenceClassification |
使用
Tokenizer和模型
1 | from transformers import AutoTokenizer, AutoModelForSequenceClassification |
Tokenizer
其中,Tokenizer的作用大致就是分词,然后把词变成的整数ID,当然有些模型会使用subword。但是不管怎么样,最终的目的是把一段文本变成ID的序列。当然它也必须能够反过来把ID序列变成文本。
细节见:https://huggingface.co/docs/transformers/tokenizer_summary
Tokenizer对象是callable,因此可以直接传入一个字符串,返回一个dict。最主要的是ID的list,同时也会返回attention mask:
我们也可以一次传入一个batch的字符串,这样便于批量处理。这时我们需要指定padding为True并且设置最大的长度:
1 | pt_batch = tokenizer( |
模型
Tokenizer的处理结果可以输入给模型,对于TensorFlow来说直接输入就行,而对于PyTorch则需要使用**来展开参数:
1 | # PyTorch |
Transformers的所有输出都是tuple,即使只有一个结果也会是长度为1的tuple:
分类任务:
1 | print(pt_outputs) |
Transformers的模型默认返回logits,如果需要概率,可以自己加softmax:
1 | import torch.nn.functional as F |
得到和前面一样的结果:
1 | print(pt_predictions) |
如果我们有输出分类对应的标签,那么也可以传入,这样它除了会计算logits还会loss:
1 | import torch |
输出为:
1 | SequenceClassifierOutput(loss=tensor(0.3167, grad_fn=<NllLossBackward>), logits=tensor([[-4.0833, 4.3364], |
语言模型 MLM【没用上,可以不看】
和前面的任务相比,语言模型本身一般很少作为一个独立的任务。它的作用通常是用来预训练基础的模型,然后也可以使用领域的未标注数据来fine-tuning语言模型。比如我们的任务是一个文本分类任务,我们可以基于基础的BERT模型在我们的分类数据上fine-tuning模型。但是BERT的基础模型是基于wiki这样的语料库进行预训练的,不一定和我们的任务很match。而且标注的成本通常很高,我们的分类数据量通常不大。但是领域的未标注数据可能不少。这个时候我们我们可以用领域的未标注数据对基础的BERT用语言模型这个任务进行再次进行pretraining,然后再用标注的数据fine-tuning分类任务。
如果我们需要fine-tuning MLM,可以参考 run_mlm.py。下面是用pipeline的例子:
1 | from transformers import pipeline |
上面会用到nlp.tokenizer.mask_token,它就是特殊的这个token。我们也可以自己构造Tokenizer和模型,步骤为:
- 构造Tokenizer和模型。比如可以使用DistilBERT从checkpoint加载预训练的模型
- 构造输入序列,把需要mask的词替换成tokenizer.mask_token
- 用tokenizer把输入变成ID list
- 获取预测的结果,它的size是词典大小,表示预测某个词的概率
- 获取topk个概率最大的词
代码如下:
1 | from transformers import AutoModelWithLMHead, AutoTokenizer |
注意这里需要使用AutoModelWithLMHead构造模型。
输出结果:
1 | for token in top_5_tokens: |
语言模型
1 | import torch |
input
输入一般会包含开头的[CLS]和结尾的[SEP],如果不想要这两个,可以通过添加add_special_tokens=False
来去掉
1 | tokenizer = BertTokenizer.from_pretrained(path_to_TAL_EduBERT) |
输出语言模型概率
我们要用到每个单词的概率,以及整句话的概率分数,输出的不是概率,最后一层没有softmax,要加softmax才是概率(没有log的概率,纯概率值)
1 | model = BertForMaskedLM.from_pretrained(path_to_TAL_EduBERT) |
联调
和CTC decoder输出的句子进行联调,看wer改进
- CTC出来n-best文本,经过lm选lm概率大的一条路径,见10.22.24.2:/home/yelong/data/wenet/examples/aishell/s0/compute-wer-lm.py
- CTC出来n-best文本以及分数,经过lm选lm概率+CTC分数加权求和最大的一条路径
用自有数据pretrain LM
/home/yelong/data/transformers/examples/pytorch/language-modeling/run_mlm.py
https://github.com/huggingface/transformers/tree/main/examples/pytorch/language-modeling
官方例子:
1 | python run_mlm.py \ |
要在您自己的训练和验证文件上运行,请使用以下命令:
1 | python run_mlm.py \ |
具体例子为:
1 | python run_mlm.py \ |
其中,data/train/data.txt就是纯文本