Hugging Face快速入门(重点讲解模型(Transformers)和数据集部分(Datasets))

2024-01-10 16:02:13 作者:欧亿体育

文章目录

本文内容

本文主要包括如下内容:

  1. Hugging Face是什么,提供了哪些内容
  2. Hugging Face模型的使用(Transformer类库)
  3. Hugging Face数据集的使用(Datasets类库)

HuggingFace简介

Hugging Face Hub和 Github 类似,都是Hub(社区)。Hugging Face可以说的上是机器学习界的Github。Hugging Face为用户提供了以下主要功能:

hugging face在NLP领域最出名,其提供的模型大多都是基于Transformer的。为了易用性,Hugging Face还为用户提供了以下几个项目:

  • Transformers(github, 官方文档): Transformers提供了上千个预训练好的模型可以用于不同的任务,例如文本领域、音频领域和CV领域。该项目是HuggingFace的核心,可以说学习HuggingFace就是在学习该项目如何使用。
  • Datasets(github, 官方文档): 一个轻量级的数据集框架,主要有两个功能:①一行代码下载和预处理常用的公开数据集; ② 快速、易用的数据预处理类库。
  • Accelerate(github, 官方文档): 帮助Pytorch用户很方便的实现 multi-GPU/TPU/fp16。
  • Space(链接):Space提供了许多好玩的深度学习应用,可以尝试玩一下。

Hugging Face模型讲解

Transforms简介

Hugging Face Transformer是Hugging Face最核心的项目,你可以用它做以下事情:

  • 直接使用预训练模型进行推理
  • 提供了大量预训练模型可供使用
  • 使用预训练模型进行迁移学习

Transformers安装

安装Transformers非常简单,直接安装即可。

pip install transformers

使用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模型

本节来介绍一下如何通过Hugging Face找到你需要的模型。

首先,我们需要到来到官网的模型模块。之后我们会看到如下界面:

其主要包含三部分:

  1. Filter: 用于筛选你想要的模型
  2. 模型列表: 展示了可使用的模型。不带前缀的是官方提供的模型,例如gpt2,而带前缀的是第三方提供的模型。
  3. 搜索框:你可以通过搜索框按名字搜索模型。

当你点进去你的模型后,你会来到如下页面:

该页面主要的几个部分:

  1. 模型介绍(Model Card): 我们可以通过该文档查看该模型都提供了哪些功能,模型的表现等。
  2. 模型文件(Files and versions): 从该模块可以下载模型文件,一般包含多种框架的(TF、Pytorch等)模型文件和配置文件等,可以用于离线加载。
  3. 测试模型(Hosted inference API): 可以直接通过该模块测试自己的模型。同时Hugging Face也提供了Http API可以调用,这样就不需要本地部署了。详情请参考:https://huggingface.co/docs/api-inference/index
  4. 使用该模型的应用(Spaces using …):这里展示了使用该模型的应用,可以点进去玩一玩。
  5. 代码样例(Use in Transformers):你可以通过该模块直接查看该模型的使用方式,直接拷贝代码到项目里就可以用了。

使用Hugging Face模型

Transformers项目提供了几个简单的API帮助用户使用Hugging Face模型,而这几个简单的API统称为AutoClass(官方文档链接),包括:

  1. AutoTokenizer: 用于文本分词
  2. AutoFeatureExtractor: 用于特征提取
  3. AutoProcessor: 用于数据处理
  4. 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模型做迁移学习的思路和普通迁移学习几乎一致:

  1. 首先选择一个和你的任务类似的任务的预训练模型,或者直接选择一个任务无关的基础模型。
  2. 从原有模型中拿出主干部分(backbone)
  3. 然后接上自己的下游任务,构建成新的模型
  4. 开始训练

这里我以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()

这样,一次参数更新就完成了,尝试把他应用到真实的项目中去吧。

Hugging Face数据集讲解

Datasets类库(github, 官方文档)可以让你非常方便的访问和分享数据集,也可以用来对NLP、CV、语音等任务进行评价(Evaluation metrics).

本节将会讲解Hugging Face数据集的使用。

安装Datasets类库

直接使用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(': Failed to establish a new connection: [Errno 11004] getaddrinfo failed'))")))

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]

到这里,数据集入门就讲完了,更多的内容就需要在你有需要的时候自己探索了。

在线咨询 拨打电话

电话

010-67916526

微信二维码

微信二维码