前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Huggingface🤗NLP笔记5:attention_mask在处理多个序列时的作用

Huggingface🤗NLP笔记5:attention_mask在处理多个序列时的作用

作者头像
beyondGuo
发布2021-10-08 17:35:27
5.4K0
发布2021-10-08 17:35:27
举报
文章被收录于专栏:SimpleAISimpleAI

「Huggingface🤗NLP笔记系列-第5集」 最近跟着Huggingface上的NLP tutorial走了一遍,惊叹居然有如此好的讲解Transformers系列的NLP教程,于是决定记录一下学习的过程,分享我的笔记,可以算是官方教程的精简+注解版。但最推荐的,还是直接跟着官方教程来一遍,真是一种享受。

  • 官方教程网址:https://huggingface.co/course/chapter1
  • 本期内容对应网址:https://huggingface.co/course/chapter2/5?fw=pt
  • 本系列笔记的GitHub:https://github.com/beyondguo/Learn_PyTorch/tree/master/HuggingfaceNLP

attention_mask在处理多个序列时的作用

现在我们训练和预测基本都是批量化处理的,而前面展示的例子很多都是单条数据。单条数据跟多条数据有一些需要注意的地方。

处理单个序列

我们首先加载一个在情感分类上微调过的模型,来进行我们的实验(注意,这里我们就不能能使用AutoModel,而应该使用AutoModelFor*这种带Head的model)。

代码语言:javascript
复制
from pprint import pprint as print  # 这个pprint能让打印的格式更好看一点
from transformers import AutoModelForSequenceClassification, AutoTokenizer
checkpoint = 'distilbert-base-uncased-finetuned-sst-2-english'
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

对一个句子,使用tokenizer进行处理:

代码语言:javascript
复制
s = 'Today is a nice day!'
inputs = tokenizer(s, return_tensors='pt')
print(inputs)
代码语言:javascript
复制
{'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1]]),
 'input_ids': tensor([[ 101, 2651, 2003, 1037, 3835, 2154,  999,  102]])}

可以看到,这里的inputs包含了两个部分:input_idsattention_mask.

模型可以直接接受input_ids

代码语言:javascript
复制
model(inputs.input_ids).logits

输出:

代码语言:javascript
复制
tensor([[-4.3232,  4.6906]], grad_fn=<AddmmBackward>)

也可以通过**inputs同时接受inputs所有的属性:

代码语言:javascript
复制
model(**inputs).logits

输出:

代码语言:javascript
复制
tensor([[-4.3232,  4.6906]], grad_fn=<AddmmBackward>)

上面两种方式的结果是一样的

但是当我们需要同时处理多个序列时,情况就有变了!

代码语言:javascript
复制
ss = ['Today is a nice day!',
      'But what about tomorrow? Im not sure.']
inputs = tokenizer(ss, padding=True, return_tensors='pt')
print(inputs)

输出:

代码语言:javascript
复制
{'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]),
 'input_ids': tensor([[  101,  2651,  2003,  1037,  3835,  2154,   999,   102,     0,     0,
             0],
        [  101,  2021,  2054,  2055,  4826,  1029, 10047,  2025,  2469,  1012,
           102]])}

然后,我们试着直接把这里的input_ids喂给模型

代码语言:javascript
复制
model(inputs.input_ids).logits  # 第一个句子原本的logits是 [-4.3232,  4.6906]

输出:

代码语言:javascript
复制
tensor([[-4.1957,  4.5675],
        [ 3.9803, -3.2120]], grad_fn=<AddmmBackward>)

发现,第一个句子的logits变了

这是因为在padding之后,第一个句子的encoding变了,多了很多0, 而self-attention会attend到所有的index的值,因此结果就变了

这时,就需要我们不仅仅是传入input_ids,还需要给出attention_mask,这样模型就会在attention的时候,不去attend被mask掉的部分。

因此,在处理多个序列的时候,正确的做法是直接把tokenizer处理好的结果,整个输入到模型中,即直接**inputs。通过**inputs,我们实际上就把attention_mask也传进去了:

代码语言:javascript
复制
model(**inputs).logits

输出:

代码语言:javascript
复制
tensor([[-4.3232,  4.6906],
        [ 3.9803, -3.2120]], grad_fn=<AddmmBackward>)

现在第一个句子的结果,就跟前面单条处理时的一样了。


往期回顾: Huggingface🤗NLP笔记4:Models,Tokenizers,以及如何做Subword tokenization Huggingface🤗NLP笔记3:Pipeline端到端的背后发生了什么 Huggingface🤗NLP笔记2:一文看清Transformer大家族的三股势力 Huggingface🤗NLP笔记1:直接使用pipeline,是个人就能玩NLP

↑ 关注我,一个干净、有货的AI知识分享平台 ↑

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SimpleAI 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • attention_mask在处理多个序列时的作用
    • 处理单个序列
      • 但是当我们需要同时处理多个序列时,情况就有变了!
      相关产品与服务
      NLP 服务
      NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档