文章目录
一、前言
Hugging Face 起初是一家总部位于纽约的聊天机器人初创服务商,他们本来打算创业做聊天机器人,然后在 github 上开源了一个 Transformers 库,虽然聊天机器人业务没搞起来,但是他们的这个库在机器学习社区迅速大火起来。
目前已经共享了超 100,000 个预训练模型,10,000 个数据集,变成了机器学习界的 github。
其之所以能够获得如此巨大的成功,一方面是让我们这些甲方企业的小白,尤其是入门者也能快速用得上科研大牛们训练出的超牛模型。
另一方面是,这种特别开放的文化和态度,以及利他利己的精神特别吸引人。
Hugging Face 上面很多业界大牛也在使用和提交新模型,这样我们就是站在大牛们的肩膀上工作,而不是从头开始,当然我们也没有大牛那么多的计算资源和数据集。
在国内 Hugging Face 也是应用非常广泛,一些开源框架本质上就是调用 Transfomer 上的模型进行微调(当然也有很多大牛在默默提供模型和数据集)。
很多 NLP 工程师招聘的条目上也明摆着要求熟悉 Hugging Face Transformer 库的使用。
因为他既提供了数据集,又提供了模型让你随便调用下载,因此入门非常简单。你甚至不需要知道什么是 GPT,BERT 就可以用他的模型了。
下面初步介绍下 Hugging Face 里面都有什么,以及怎么调用 BERT 模型做个简单的任务。
参考文献:
https://zhuanlan.zhihu.com/p/535100411
二、可以获得什么?
内容:
Hugging Face 的官方网站:
https://huggingface.co/
- Datasets:数据集,以及数据集的下载地址;
- Models:各个预训练模型;
- course:免费的 NLP 课程,可惜都是英文的;
- docs:文档。
在 NLP 领域,在 Hugging Face 上面数据集和预训练模型的数量以英语为最为众多,远超其他国家的总和(见下图)。
就预训练模型来说,排名第二的是汉语。
就数据集来说,汉语远远少于英语,也少于法,德,西班牙等语言,甚至少于阿拉伯语和波兰语。
这严重跟我想象中的 AI 超级大国及其不匹配。
我想一方面因为数据集的积累都需要很多年,中文常用的(PKU,MSRA)数据集都是十几年前留下的,而我们 AI 和经济的崛起也不过是最近十年的事情。
另一方面,数据集都是大价钱整理出来的,而且可以不断的利用他产生新的模型,这样的大杀器怎可随意公布。发布预训练模型可以带来论文,数据集可啥也带不来,基本上中日韩等的数据集明显偏少。
三、入门实践
3.1 帮助文档
接下来的内容参考了下面的内容,初步带你入门 Hugging Face,简单了解如何调用 BERT 模型:
参考网站:
https://www.cnblogs.com/dongxiong/p/12763923.html
https://huggingface.co/docs/transformers/model_doc/bert
3.2 安装
Transformers 库 github 地址在:
https://github.com/huggingface/transformers
安装方法,在命令行执行(conda 的话在 anaconda propmt):
安装最新的版本:
pip install transformers
安装指定版本:
pip install transformers ==4.0
如果你是 conda 的话,4.0 以后的版本才会有:
conda install -c huggingface transformers
测试下安装是否成功:
from transformers import pipeline
3.3 模型的组成
一般 Transformer 模型有三个部分组成:
- tokennizer
- Model
- Post processing
我们可以看到三个部分的具体作用:
Tokenizer 就是把输入的文本做切分,然后变成向量,Model 负责根据输入的变量提取语义信息,输出 logits;最后 Post Processing 根据模型输出的语义信息,执行具体的 NLP 任务,比如情感分析,文本自动打标签等;可见 Model 是其中的核心部分,Model 又可以分为三种模型,针对不同的 NLP 任务,需要选取不同的模型类型:Encoder 模型(如 Bert,常用于句子分类、命名实体识别(以及更普遍的单词分类)和抽取式问答。),Decoder 模型(如 GPT,GPT2,常用于文本生成),以及 sequence2sequence 模型(如 BART,常用于摘要,翻译,生成性问答等)。
说了很多理论的内容,我们可以在 Hugging Face 的官网,随便找一个预训练模型具体看看包含哪些文件。
在这里我举了一个中文的例子 “Bert-base-Chinese”(中文还有其他很优秀的预训练模型,比如哈工大和科大讯飞提供的:roberta-wwm-ext,百度提供的:ernie)。这个模型据说是根据中文维基百科内容训练的,因此语义内容可能不是足够丰富,毕竟其他大佬们提供的数据更多。
README.md 一般是模型的介绍,包括使用方法都会放到里面,不介绍了。其他最重要的组成部分,大概分为三类:
config:
控制模型的名称、最终输出的样式、隐藏层宽度和深度、激活函数的类别等。这些参数我补齐了说明,对于初学者来说,大家一般不需要调整。这些参数都可以通过 configuration 类更改。
{"architectures":["BertForMaskedLM"],"attention_probs_dropout_prob":0.1,"directionality":"bidi","hidden_act":"gelu","hidden_dropout_prob":0.1,"hidden_size":768,"initializer_range":0.02,"intermediate_size":3072,"layer_norm_eps":1e-12,"max_position_embeddings":512,"model_type":"bert","num_attention_heads":12,"num_hidden_layers":12,"pad_token_id":0,"pooler_fc_size":768,"pooler_num_attention_heads":12,"pooler_num_fc_layers":3,"pooler_size_per_head":128,"pooler_type":"first_token_transform","type_vocab_size":2,"vocab_size":21128}
tokenizer(包含三个文件):
这些文件是 tokenizer 类生成的,或者处理的,只是处理文本,不涉及任何向量操作。
vocab.txt 是词典文件(打开就是单个字符,我这里用的是 bert-base-chinsese,可以看到里面都是保留符号和单个汉字索引,字符)
tokenizer.json 和 config 是分词的配置文件,根据 vocab 信息和你的设置更新,里面把 vocab 都按顺序做了索引,将来可以根据编码生成 one-hot 向量,然后跟 embeding 训练的矩阵相乘,就可以得到该字符的向量。
模型文件一般是 tensorflow(上图中的 h5 文件)和 Pytorch(上图中的 bin 文件)的都有,因为作者只是单纯的在学习 torch,所以以后的文章都只介绍 torch。
3.4 BERT模型的使用
介绍完了模型库都有哪些内容,下面我们可以导入模型试一试怎么使用:
3.4.1 导入模型
利用官方的 hub 导入模型;下面导入了一个 BertModel ;在官方的教程中推进使用 pipeline 导入模型的方法:
import torch
from transformers import BertModel, BertTokenizer, BertConfig
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
config = BertConfig.from_pretrained('bert-base-chinese')
config.update({'output_hidden_states':True})
model = BertModel.from_pretrained("bert-base-chinese",config=config)
利用 pipeline 的方式也是一样的可以导入模型哈,方式如下:
from transformers import AutoModel
checkpoint ="bert-base-chinese"
model = AutoModel.from_pretrained(checkpoint)
因为 Hugging Face 官网在国外,自动下载可能比较费劲。
默认下载地址在这里:
- 使用 Windows 模型保存的路径在 C:\Users[用户名].cache\torch\transformers\ 目录下,根据模型的不同下载的东西也不相同;
- 使用 Linux 模型保存的路径在 ~/.cache/torch/transformers/ 目录下
如果自动下载总是中断的话,可以考虑用国内的源,或者手工下载之后指定位置。(Hugging Face 官网,选择 models 菜单,然后搜索自己想要的模型,然后把里面的文件下载下来,其中体积较大的有 tf 的有 torch 的,根据自己需要下载)。
import transformers
MODEL_PATH =r"D:\\test\\bert-base-chinese"# 导入模型
tokenizer = transformers.BertTokenizer.from_pretrained(r"D:\\test\\bert-base-chinese\\bert-base-chinese-vocab.txt")# 导入配置文件
model_config = transformers.BertConfig.from_pretrained(MODEL_PATH)# 修改配置
model_config.output_hidden_states =True
model_config.output_attentions =True# 通过配置和路径导入模型
model = transformers.BertModel.from_pretrained(MODEL_PATH,config = model_config)
3.4.2 使用模型
上一步我们已经把模型加载进来了,在这里,尝试一下这个模型怎么样,看看能不能把相关的语义带入进来。
我们之前文章介绍了 bert 的两个任务(MLM 和 NSP),这一节,我们一起测试这两个任务的效果。首先我们逐步来看看 BERT 每个部分的输出都是什么:
3.4.2.1 tokenizer
上面代码可以看到他实例化了 BertTokenizer 类,它是基于 WordPiece 方法的,先看看他有哪些参数:
( vocab_file,do_lower_case =True,do_basic_tokenize =True,never_split =None,unk_token ='[UNK]',sep_token ='[SEP]',pad_token ='[PAD]',cls_token ='[CLS]',mask_token ='[MASK]',tokenize_chinese_chars =True,strip_accents =None,**kwargs )
- vocab_file:这里是放置词典的地址;
- do_lower_case,是否都变成小写,默认是 True;
- do_basic_tokenize,做 wordpiece 之前是否要做 basic tokenize;
- 下面的都是一些关键字的确认。
- 还有就是是否分开中文字符,因为bert是面向英文的所有有这些设置,一般不用改,当然我们这里的案例也只是读取了预训练模型。
示例如下,可以看出 BERT 对中文是字符级别的分词,对待英文是到 sub-word 级别的:
print(tokenizer.encode("生活的真谛是美和爱"))# 对于单个句子编码print(tokenizer.encode_plus("生活的真谛是美和爱","说的太好了"))# 对于一组句子编码# 输出结果如下:[101,4495,3833,4638,4696,6465,3221,5401,1469,4263,102]{'input_ids':[101,4495,3833,4638,4696,6465,3221,5401,1469,4263,102,6432,4638,1922,1962,749,102],'token_type_ids':[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1],'attention_mask':[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]}# 也可以直接这样用
sentences =['网络安全开发分为三个层级','车辆系统层级网络安全开发','车辆功能层级网络安全开发','车辆零部件层级网络安全开发','测试团队根据车辆网络安全目标制定测试技术要求及测试计划','测试团队在网络安全团队的支持下,完成确认测试并编制测试报告','在车辆确认结果的基础上,基于合理的理由,确认在设计和开发阶段识别出的所有风险均已被接受',]
test1 = tokenizer(sentences)print(test1)# 对列表encoderprint(tokenizer("网络安全开发分为三个层级"))# 对单个句子encoder
输出结果为:
[101,4495,3833,4638,4696,6465,3221,5401,1469,4263,102]{'input_ids':[101,4495,3833,4638,4696,6465,3221,5401,1469,4263,102,6432,4638,1922,1962,749,102],'token_type_ids':[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1],'attention_mask':[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]}{'input_ids':[[101,5381,5317,2128,1059,2458,1355,1146,711,676,702,2231,5277,102],[101,6756,6775,5143,5320,2231,5277,5381,5317,2128,1059,2458,1355,102],[101,6756,6775,1216,5543,2231,5277,5381,5317,2128,1059,2458,1355,102],[101,6756,6775,7439,6956,816,2231,5277,5381,5317,2128,1059,2458,1355,102],[101,3844,6407,1730,7339,3418,2945,6756,6775,5381,5317,2128,1059,4680,3403,1169,2137,3844,6407,2825,3318,6206,3724,1350,3844,6407,6369,1153,102],[101,3844,6407,1730,7339,1762,5381,5317,2128,1059,1730,7339,4638,3118,2898,678,8024,2130,2768,4802,6371,3844,6407,2400,5356,1169,3844,6407,2845,1440,102],[101,1762,6756,6775,4802,6371,5310,3362,4638,1825,4794,677,8024,1825,754,1394,4415,4638,4415,4507,8024,4802,6371,1762,6392,6369,1469,2458,1355,7348,3667,6399,1166,1139,4638,2792,3300,7599,7372,1772,2347,6158,2970,1358,102]],'token_type_ids':[[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]],'attention_mask':[[1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]}
来看一下这个输出:
对于单个句子是上面那种,它只输出句子 tok 之后的 id,我们注意到已经加好 [CLS], [SEP] 等标识符了;(查询 tokenizer 可知,101 是 [CLS], 102 是 [SEP])除了 input_ids 之外,还自动编码了 token_type_ids,attention_mask。
3.5 model
model 实例化了 BertModel 类,除了初始的 Bert、GPT 等基本模型,针对不同的下游任务,定义了 BertForQuestionAnswering,BertForMultiChoice,BertForNextSentencePrediction 以及 BertForSequenceClassification 等下游任务模型。
模型导出时将生成 config.json 和 pytorch_model.bin 参数文件,这两个文件前面已将介绍了,一个是配置文件一个是 torch 训练后 save 的文件。
因为中文是字符级的 tok,所以做 MLM 任务不是很理想,所以下面我用英文的 base 模型示例一个 MLM 任务:
from transformers import pipeline
# 运行该段代码要保障你的电脑能够上网,会自动下载预训练模型,大概420M
unmasker = pipeline("fill-mask",model ="bert-base-uncased")# 这里引入了一个任务叫fill-mask,该任务使用了base的bert模型
unmasker("The goal of life is [MASK].", top_k=5)# 输出mask的指,对应排名最前面的5个,也可以设置其他数字# 输出结果如下,似乎都不怎么有效哈。[{'score':0.10933303833007812,'token':2166,'token_str':'life','sequence':'the goal of life is life.'},{'score':0.03941883146762848,'token':7691,'token_str':'survival','sequence':'the goal of life is survival.'},{'score':0.032930608838796616,'token':2293,'token_str':'love','sequence':'the goal of life is love.'},{'score':0.030096106231212616,'token':4071,'token_str':'freedom','sequence':'the goal of life is freedom.'},{'score':0.024967126548290253,'token':17839,'token_str':'simplicity','sequence':'the goal of life is simplicity.'}]
3.6 后处理
后处理通常要根据你选择的模型来确定,一般模型的输出是 logits,其包含我们需要的语义信息,然后后处理是经过一个激活函数输出我们可以使用的向量,比如 softmax 层做二分类,会输出对应两个标签的概率值,然后就可以轻松转化为我们需要的信息啦。
版权归原作者 旅途中的宽~ 所有, 如有侵权,请联系我们删除。