18

NLP文本向量化必备:BERT句向量争议与transformers、sentence-transformers向量生成动...

 2 years ago
source link: https://mp.weixin.qq.com/s?__biz=MjM5ODkzMzMwMQ%3D%3D&%3Bmid=2650429987&%3Bidx=3&%3Bsn=a750b7873711616821c7ce3282cb0488
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
640?wx_fmt=jpeg

在前面的文章《NLP文本向量化必备:Gensim、Sklearn中的8种向量化工具概述与实践实操总结》中,我们介绍了one-hot、weighted one-hot 、主题向量表示等方法,并给出了Gensim、Sklearn的快速调用方式。

而在BERT大行其道的今天,也可以使用预训练BERT快速得到向量表示。

同样的,当前也提供了一些快速调用的接口,如transformers、sentence-transformers,本文主要围绕这个开放模型进行实践,并对BERT得到的动态句向量的性能进行介绍和剖析。

一、使用transformers生成动态词向量与句向量

Hugging Face生态及Hugging Face主干库:Transformer模型库、Datasets数据集库、Tokenizer分词库。通过预训练好的Bert模型,得到不同语境下,不同句子的句向量。相比于word2vec、glove这种静态词向量,会含有更丰富的语义,并能解决不同场景不同意思的问题。

1、安装

pip install torch. 
pip install -U transformers

地址:https://huggingface.co/bert-base-uncasedl 在Hugging Face中,公开了多种模型,如下:

640?wx_fmt=png

2、参考论文

《Attention Is All You Need》 https://papers.nips.cc/paper/2017/file/3f5ee243547dee91fbd053c1c4a845aa-Paper.pdf

3、使用实例

>>> from transformers import BertTokenizer, BertModel
>>> import torch
## 需要下载对应的预训练模型,包括:模型bin文件、vocab.txt和config.json,这里选用bert-base-uncased
>>> tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
>>> model = BertModel.from_pretrained("bert-base-uncased")
>>> text = "等潮水退去,就知道谁没穿裤子"
>>> text_dict = tokenizer.encode_plus(text, add_special_tokens=True, return_attention_mask=True)
>>> text_dict
{'input_ids': [101, 100, 100, 1893, 100, 100, 1989, 100, 100, 1957, 100, 100, 100, 100, 1816, 102], 'token_type_ids': [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]}
>>> input_ids = torch.tensor(text_dict['input_ids']).unsqueeze(0)
>>> input_ids
tensor([[ 101,  100,  100, 1893,  100,  100, 1989,  100,  100, 1957,  100,  100,
          100,  100, 1816,  102]])
>>> token_type_ids = torch.tensor(text_dict['token_type_ids']).unsqueeze(0)
>>> token_type_ids 
tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
>>> attention_mask = torch.tensor(text_dict['attention_mask']).unsqueeze(0)
tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
## Bert的输入要有三个向量:(1)input_ids (2)token_type_ids (3)attention_mask。这三个向量可以通过一行代码获得:
>>> res = model(input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids)

res是一个包含2个元素的tuple(根据config的不同,返回的元素个数也不同,默认是2个):

第一个是sequnce_output,即last_hidden_state,即16*768维度

>>> (res[0].detach().squeeze(0)).shape
torch.Size([16, 768])

第二个是pooler_output,维度是768,为所有向量的池化结果。

>>> (res[1].detach().squeeze(0)).shape
torch.Size([768])

二、BERT得到的动态句向量在语义表示性能并非最好?

实际上,当前使用BERT直接得到句子向量,然后送到下游使用,尤其在语义相似度计算上,性能不太如意,在更多情况下,BERT第一层和最后一层的平均已经成我们的标配了,就是比直接取CLS好很多,是个值得信赖的baseline,如sbert论文中的分析结果。

640?wx_fmt=png

所以,会有一个问题,即

1、BERT的CLS向量并不奏效?

来自于知乎https://www.zhihu.com/question/505359496的问题:

为什么Bert中的CLS在未fine tune时作为sentence embedding性能非常糟糕?

下面的回答十分有趣:

根本原因是BERT在预训练任务中[CLS]句向量表示的是句子对之间是否关联,与预训练任务的定义息息相关,如果我们将上下文是否相关的数据作为训练数据,那么在学习过程中,应该学习到句子是否关联,那么关联的句子更相似,而不是相似的句子。

2、BERT生成的动态词向量也并不那么友好?

知乎https://zhuanlan.zhihu.com/p/430580960中说明了bert的两种不足:

1)Bert encode出来的向量表达具有各向异性

在ICLR里有两篇文章(ICLR2019文章、 ICLR2020)研究表明,Transform模型出来的向量表达(如Bert、GPT2)就是会产生各向异性,且也给出了各向异性的表现状态,就是向量会不均匀分布,且充斥在一个狭窄的锥形空间下。

由于词向量是有维度的,每个维度上基向量单位向量长度不一样,就是各向异性的,这样就会造成我们计算向量相似度的时候产生偏差。

这种性质也限制了句子向量的语义表达能力,因此当采用计算bert encode句子相似度,采用cos或dot是无法很好的衡量出两个句子的相似度,因为bert向量不是基于一个标准正交基得到的。

2)分布不均匀,低频词分布稀疏,高频词分布紧密

由于BERT的训练过程,其偏向于高频词,所以得到的向量话会表现成高频词会集中在头部,离原点近,低频词会集中在尾部,离远点远高频词与低频词分布在不同的区域,那高频词与低频词之间的相识度也就没法计算了。

这也反映出来的就是明显的低频词没有得到一个很好的训练。同时,高频词频次高,也会主宰句子表达。

所以,为了解决这两类问题,Bert-flow还有Bert-whitening就出现了,这两篇文章解决的都是问题是一致的,都是想解决句子embedding的各向异性及向量的分布不均匀问题。

Bert-flow《On the Sentence Embeddings from Pre-trained Language Models》采用一个变换,使用bert获取其原始embedding,然后将可逆变换映射到一个高斯分布上。其中bret-flow模型默认使用了最后两层的avg pooling(last2avg),将Bert encode的句子表达转换到一个各向同性且分布较均匀的空间,而标准的高斯分布刚好是一个各向同性的空间,且是一个凸函数,语义分布也更平滑均匀。

640?wx_fmt=png

地址:https://arxiv.org/abs/2011.05864

Bert-whitening《你可能不需要BERT-flow:一个线性变换媲美BERT-flow》提出通过一个白化的操作直接校正局向量的协方差矩阵,是将现存的Bert向量空间分布进行白化操作,也达到了一个较好的结果。

地址:https://spaces.ac.cn/archives/8069

此外,SimCSE、ESimCSE以及Sentence-BERT也是可以采用的方法,无监督对比学习SimCSE直接采用dropout小技巧加强版SimCS,主要解决了SimCSE对比学习中,正样本与原样本长度一样,会让模型学到相同的句长的更容易成为正样本问题,Sentence-BERT框架提供了一种简便的方法来计算句子和段落的向量表示。

三、使用sentence-transformers生成动态词向量与句向量

sentence-transformer框架提供了一种简便的方法来计算句子和段落的向量表示(也称为句子嵌入)。这些模型基于诸如BERT/RoBERTa/XLM-RoBERTa等模型,并且经过专门调整以优化向量表示,以使具有相似含义的句子在向量空间中接近。

640?wx_fmt=png

1、安装

pip install -U sentence-transformers

地址:https://www.sbert.net/index.html

与bert一样,给出了许多预训的模型

640?wx_fmt=png

2、参考论文

《Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks》

地址:https://arxiv.org/abs/1908.10084

3、使用实例

>>> from sentence_transformers import SentenceTransformer, util
>>> model = SentenceTransformer('distiluse-base-multilingual-cased')
# distiluse-base-multilingual-cased 蒸馏得到的,官方预训练好的模型
Downloading: 100%|███████████████████████████████████████████████████████████████████████████████████████████| 690/690 [00:00<00:00, 265kB/s]
Downloading: 100%|███████████████████████████████████████████████████████████████████████████████████████| 2.37k/2.37k [00:00<00:00, 873kB/s]
Downloading: 100%|███████████████████████████████████████████████████████████████████████████████████████████| 607/607 [00:00<00:00, 224kB/s]
Downloading: 100%|██████████████████████████████████████████████████████████████████████████████████████████| 122/122 [00:00<00:00, 47.8kB/s]
Downloading: 100%|███████████████████████████████████████████████████████████████████████████████████████████| 341/341 [00:00<00:00, 125kB/s]
Downloading: 100%|████████████████████████████████████████████████████████████████████████████████████████| 539M/539M [00:19<00:00, 28.3MB/s]
Downloading: 100%|████████████████████████████████████████████████████████████████████████████████████████| 53.0/53.0 [00:00<00:00, 20.8kB/s]
Downloading: 100%|██████████████████████████████████████████████████████████████████████████████████████████| 112/112 [00:00<00:00, 40.8kB/s]
Downloading: 100%|███████████████████████████████████████████████████████████████████████████████████████| 1.96M/1.96M [00:06<00:00, 290kB/s]
Downloading: 100%|███████████████████████████████████████████████████████████████████████████████████████████| 528/528 [00:00<00:00, 201kB/s]
Downloading: 100%|█████████████████████████████████████████████████████████████████████████████████████████| 996k/996k [00:07<00:00, 135kB/s]
Downloading: 100%|██████████████████████████████████████████████████████████████████████████████████████████| 190/190 [00:00<00:00, 71.3kB/s]
Downloading: 100%|██████████████████████████████████████████████████████████████████████████████████████████| 114/114 [00:00<00:00, 42.2kB/s]
Downloading: 100%|██████████████████████████████████████████████████████████████████████████████████████| 1.58M/1.58M [00:00<00:00, 2.72MB/s]
>>> emb1 = model.encode('Natural language processing is a hard task for human')
>>> emb2 = model.encode('自然语言处理对于人类来说是个困难的任务')
>>> emb1
array([ 2.58186590e-02,  4.65703346e-02,  4.25276496e-02, -1.67875513e-02,
        5.56012690e-02, -3.44308838e-02, -6.53978735e-02,  1.77450478e-02,
       -3.47155109e-02,  2.86140274e-02,  2.48657260e-02,  7.94188876e-04,
        5.09755425e-02, -1.76107027e-02, -1.04308855e-02,  7.61642214e-03,
        ...  ...
       -1.17232790e-02,  7.92307183e-02, -2.17613694e-03, -1.39151979e-03])
>>> emb1.shape
(512,)       
>>> cos_sim = util.pytorch_cos_sim(emb1, emb2)
>>> cos_sim
tensor([[0.8960]])

1、https://www.zhihu.com/question/505359496/answer/2272544215

2、https://arxiv.org/abs/1908.10084

3、https://www.sbert.net/index.html

4、https://huggingface.co/bert-base-uncasedl

5、https://papers.nips.cc/paper/2017/file/3f5ee243547dee91fbd053c1c4a845aa-Paper.pdf

6、https://www.zhihu.com/question/505359496

0?wx_fmt=png
AINLP
一个有趣有AI的自然语言处理公众号:关注AI、NLP、机器学习、推荐系统、计算广告等相关技术。公众号可直接对话双语聊天机器人,尝试自动对联、作诗机、藏头诗生成器,调戏夸夸机器人、彩虹屁生成器,使用中英翻译,查询相似词,测试NLP相关工具包。
343篇原创内容
Official Account
进技术交流群请添加AINLP小助手微信(id: ainlper)
请备注具体方向+所用到的相关技术点
640?wx_fmt=jpeg

关于AINLP

AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLPer(id:ainlper),备注工作/研究方向+加群目的。

640?wx_fmt=jpeg

阅读至此了,分享、点赞、在看三选一吧🙏


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK