本文主要包括如下内容:
Hugging Face Hub和 Github 类似,都是Hub(社区)。Hugging Face可以说的上是机器学习界的Github。Hugging Face为用户提供了以下主要功能:
hugging face在NLP领域最出名,其提供的模型大多都是基于Transformer的。为了易用性,Hugging Face还为用户提供了以下几个项目:
Hugging Face Transformer是Hugging Face最核心的项目,你可以用它做以下事情:
安装Transformers非常简单,直接安装即可。
pip install transformers
如果你的任务是一个比较常见的,大概率可以直接使用Transformer提供的PipelineAPI解决,其使用方式非常简单,可以说是直接用即可。
from transformers import pipeline
translator = pipeline("translation_en_to_fr")
print(translator("How old are you?"))
[{'translation_text': ' quel âge êtes-vous?'}]
对于部分特定任务,官方并没有提供相应的模型,但你也可以到官网搜索模型,然后显示指定即可。在加载模型时,你有可能会因为缺少一些库而报错,这个时候,只需要安装对应的库,然后重启即可。
!pip install sentencepiece
translator = pipeline("translation_en_to_zh", model='Helsinki-NLP/opus-mt-en-zh')
translator("I'm learning deep learning.")
[{'translation_text': '我在学习深思熟虑'}]
更多Pipeline请参考官方文档:https://huggingface.co/docs/transformers/v4.21.0/en/main_classes/pipelines
本节来介绍一下如何通过Hugging Face找到你需要的模型。
首先,我们需要到来到官网的模型模块。之后我们会看到如下界面:
其主要包含三部分:
当你点进去你的模型后,你会来到如下页面:
该页面主要的几个部分:
Transformers项目提供了几个简单的API帮助用户使用Hugging Face模型,而这几个简单的API统称为AutoClass
(官方文档链接),包括:
AutoTokenizer
: 用于文本分词AutoFeatureExtractor
: 用于特征提取AutoProcessor
: 用于数据处理AutoModel
: 用于加载模型它们的使用方式均为: AutoClass.from_pretrain("模型名称")
,然后就可以用了。例如:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
tokenizer("I'm learning deep learning.")
{'input_ids': [101, 1045, 1005, 1049, 4083, 2784, 4083, 1012, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]}
通常一个模型会包含上述4个中的部分功能,例如,对于bert-base-uncased
模型,就包含“分词”和“模型”两项功能,我们可以通过代码样例(Use in Transformers) 模块查看:
也不是所有的模型都可以使用
AutoModel
,具体还要看模型的代码示例。
很多情况下,Hugging Face提供的模型并不能满足我们的需要,所以我们还是要自己训练模型的。此时我们可以使用Hugging Face提供的预训练模型来进行迁移学习,本节将会介绍如何使用Hugging Face进行迁移学习。
使用Hugging Face模型做迁移学习的思路和普通迁移学习几乎一致:
这里我以bert-base-uncased
模型作为例子,进行一次模型参数更新操作,假设我的任务是一个二分类的情感分类问题。
首先,我们先尝试一下运行该模型,我们将该模型的Use in Transformers中的样例代码拷贝过来:
from transformers import AutoTokenizer, AutoModelForMaskedLM
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModelForMaskedLM.from_pretrained("bert-base-uncased")
Some weights of the model checkpoint at bert-base-uncased were not used when initializing BertForMaskedLM: ['cls.seq_relationship.weight', 'cls.seq_relationship.bias']
- This IS expected if you are initializing BertForMaskedLM from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).
- This IS NOT expected if you are initializing BertForMaskedLM from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).
之后我们需要尝试使用一下该模型:
inputs = tokenizer("Learning is a very happy [MASK].", return_tensors='pt')
print(inputs)
{'input_ids': tensor([[ 101, 4083, 2003, 1037, 2200, 3407, 103, 1012, 102]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1]])}
model(**inputs).logits.argmax(dim=-1)
tensor([[1012, 4083, 2003, 1037, 2200, 3407, 2832, 1012, 1012]])
通常HuggingFace模型的的使用都是分两步,首先分词(其他模型可能是特征提取
AutoFeatureExtractor
等),然后将第一步的结果作为模型的入参。注意第一步通常要指定return_tensors='pt'
来让其返回tensor类型的数据。我们也可以使用Jupyter中的tokenizer?
方式来查看其使用方法。
tokenizer.convert_ids_to_tokens(2832)
'process'
这里我们得到了和页面同样的数据,
模型测试完毕,接下来开始正式进入迁移学习。
bert-base-uncased
的任务是Fill-Mask
,也就是填空任务,而我们的任务是情感分类,所以我们要把原本的分类器给去掉。我们先打印一下当前模型:
print(model)
BertForMaskedLM(
(bert): BertModel(
。。。略
)
(cls): BertOnlyMLMHead(
。。。略
(decoder): Linear(in_features=768, out_features=30522, bias=True)
)
)
)
我们可以从输出中看到,bert-base-uncased
模型由两大部分构成,bert
和最后的分类层cls
,我们做迁移学习,肯定是要前面的bert
层,所以我们可以这么提取其bert
层:
print(model.bert)
BertModel(
。。。略
)
我们来尝试一下使用model.bert
:
outputs = model.bert(**inputs)
print(outputs)
print(outputs.last_hidden_state.size())
BaseModelOutputWithPoolingAndCrossAttentions(last_hidden_state=tensor([[[ 0.0568, 0.1662, 0.0943, ..., -0.0346, -0.0636, 0.1689],
[-0.0402, 0.0757, 0.1923, ..., -0.0217, -0.0459, 0.0711],
[-0.1038, -0.0372, 0.5063, ..., -0.1587, 0.0475, 0.5513],
...,
[ 0.1763, -0.0111, 0.1922, ..., 0.1891, -0.1079, -0.2163],
[ 0.8013, 0.4953, -0.2258, ..., 0.1501, -0.7685, -0.3709],
[ 0.0572, 0.3405, 0.6527, ..., 0.4695, -0.0455, 0.3055]]],
grad_fn=), pooler_output=None, hidden_states=None, past_key_values=None, attentions=None, cross_attentions=None)
torch.Size([1, 9, 768])
可以看到,我们得到的是bert输出的隐层信息,我们可以将该隐层信息输入到一个线性层进行情感分类,然后进行损失函数计算,进而反向传播更新参数即可。有一点需要注意,上面返回的隐层Shape为(1, 9, 768),其中1为batch_size,9是因为tokens有9个,768是每个token对应的向量的维度。我们在使用bert进行情感分类时,通常是使用第一个token(
)的结果。
import torch
from torch import nn
# 定义最后的二分类线性层
cls = nn.Sequential(
nn.Linear(768, 1),
nn.Sigmoid()
)
# 使用二分类常用的Binary Cross Entropy Loss
criteria = nn.BCELoss()
# 这里只对最后的线性层做参数更新
optimizer = torch.optim.SGD(cls.parameters(), lr=0.1)
# 取隐层的第一个token()的输出作为cls层的输入,然后与label进行损失计算
loss = criteria(cls(outputs.last_hidden_state[:, 0, :]), torch.FloatTensor([[1]]))
loss.backward()
optimizer.step()
optimizer.zero_grad()
这样,一次参数更新就完成了,尝试把他应用到真实的项目中去吧。
Datasets类库(github, 官方文档)可以让你非常方便的访问和分享数据集,也可以用来对NLP、CV、语音等任务进行评价(Evaluation metrics).
本节将会讲解Hugging Face数据集的使用。
直接使用pip安装即可:
pip install datasets
如果要使用语音(Audio)数据集,则需要执行如下命令:
pip install datasets[audio]
同理,图片(Image)数据为:
pip install datasets[vision]
首先,我们需要打开Hugging Face Datasets页面,与Models页面类似,这里展示了Hugging Face的数据集,可以使用标签或名称进行筛选:
我们可以点进我们感兴趣的数据集,查看详情:
Hugging Face的数据集通常包括多个子集(subset),并且分成了train、validation和test三份。你可以通过预览区域查看你需要的子集。
加载Hugging Face只需要用到datasets.load_dataset
一个方法就够了。使用方法也很简单,直接填入要加载的数据集就可以了:
from datasets import load_dataset
dataset = load_dataset("glue")
ConnectionError: Couldn't reach https://raw.githubusercontent.com/huggingface/datasets/2.4.0/datasets/glue/glue.py (ConnectionError(MaxRetryError("HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /huggingface/datasets/2.4.0/datasets/glue/glue.py (Caused by NewConnectionError('
Hugging Face的数据集都是放在github上的,所以国内估计很难下载成功。这就要用到
load_dataset
的加载本地数据集。关于如何离线下载Hugging Face数据集,可参考该篇文章
我们这里离线下载好数据集后,将其拷贝到当前目录下,目录结构为:
-- glue
-- dummy # glue的数据子集就放在这个目录下
-- ax
-- cola
...
-- dataset_infos.json
-- glue.py
-- README.md
我们现在开始来加载本地数据集:
dataset = load_dataset(path="./glue", name="cola")
print(dataset)
DatasetDict({
train: Dataset({
features: ['sentence', 'label', 'idx'],
num_rows: 8551
})
validation: Dataset({
features: ['sentence', 'label', 'idx'],
num_rows: 1043
})
test: Dataset({
features: ['sentence', 'label', 'idx'],
num_rows: 1063
})
})
对于这种有子集的数据集,必须要指定你要加载的子集名称
可以看到,dataset
是一个Dict类型的,那么就可以按照dict的方式访问数据集:
dataset['train']
Dataset({
features: ['sentence', 'label', 'idx'],
num_rows: 8551
})
dataset['train']['sentence'][:5]
["Our friends won't buy this analysis, let alone the next one we propose.",
"One more pseudo generalization and I'm giving up.",
"One more pseudo generalization or I'm giving up.",
'The more we study verbs, the crazier they get.',
'Day by day the facts are getting murkier.']
dataset['train']['label'][:5]
[1, 1, 1, 1, 1]
到这里,数据集入门就讲完了,更多的内容就需要在你有需要的时候自己探索了。