首页
Preview

BERT用于衡量文本相似性

作者:Kevin Musgrave

现在我们似乎只谈论BERT,BERT那。我想写点别的,但BERT太好了——所以这篇文章将涉及BERT和序列相似性!

自然语言处理(NLP)的一个重要部分依赖于高维空间中的相似性。通常,NLP解决方案将处理一些文本,以创建表示所述文本的大向量/数组,然后执行多个转换。

这是高维魔法。

句子相似性是高维魔法如何强大的最明显的例子之一。

逻辑是这样的:

  • 取一个句子,将其转换为向量。
  • 取许多其他句子,并将它们转换为向量。
  • 找到之间距离(欧几里得距离)最小或角度(余弦相似度)最小的句子——更多信息在这里。
  • 现在我们有了句子之间的语义相似性的度量——很容易!

在高层次上,除此之外就没有太多了。但当然,我们希望更详细地了解发生了什么,并在Python中实现它!所以,让我们开始吧。

为什么BERT有用

BERT,正如我们已经提到的,是NLP的MVP。其中一部分原因是BERT能够将单词的含义嵌入到密集的向量中。

我们称它们为_dense_向量,因为向量中的每个值都有一个值,并且有一个原因成为该值——这与_sparse_向量形成对比,例如one-hot编码向量,其中大多数值都是0

BERT在创建这些密集向量方面非常出色,每个编码器层(有几个)输出一组密集向量。

BERT基础网络——其中隐藏层表示用绿色标出。

对于BERT base,这将是一个包含768的向量。这768个值包含单个标记的数字表示——我们可以使用它作为上下文词嵌入。

因为每个编码器输出了一个这样的向量来表示每个标记,所以实际上我们正在查看大小为768的张量,其中包含_token_的数量。

我们可以采用这些张量——并对它们进行转换以创建输入序列的语义表示。然后我们可以采取我们的相似度度量并计算不同序列之间的相应相似度。

最简单和最常提取的张量是_last_hidden_state_张量——这是BERT模型方便地输出的。

当然,这是一个相当大的张量——512x768——我们想要一个向量将我们的相似度度量应用于它。

为此,我们需要将我们的_last_hidden_states_张量转换为768维的向量。

创建向量

为了将我们的_last_hidden_states_张量转换为我们的向量,我们使用平均池化操作。

每个这些512个标记都有一个相应的768个值。此池操作将获取所有标记嵌入的平均值,并将它们压缩成单个768向量空间——创建一个“句子向量”。

同时,我们不能只取平均激活。我们需要考虑空值填充标记(我们不应该包括它们)。

在代码中

这对过程的理论和逻辑非常好,但我们如何在现实中应用它呢?

我们将概述两种方法——简单的方法和稍微复杂的方法。

简单——Sentence-Transformers

我们实现我们刚刚涵盖的所有内容的最简单方法是使用sentence-transformers库——它将大部分这个过程包装成几行代码。

首先,我们使用pip install sentence-transformers安装sentence-transformers。这个库在幕后使用HuggingFace的_transformers_,所以我们实际上可以在这里找到_sentence-transformers_模型。

我们将使用<a class="af pr" href="https://huggingface.co/sentence-transformers/bert-base-nli-mean-tokens" rel="noopener ugc nofollow" target="_blank">bert-base-nli-mean-tokens</a>模型——它实现了我们到目前为止讨论的相同逻辑。

(它还使用128个输入标记,而不是512个)。

让我们创建一些句子,初始化我们的模型并对句子进行编码:

太好了,现在我们有四个句子嵌入——每个嵌入包含768个值。

现在我们要做的是获取这些嵌入并找到它们之间的余弦相似性。所以对于句子0:

三年后,棺材仍然装满了果冻。

我们可以使用以下代码找到最相似的句子:

现在,这是更简单、更抽象的方法。只需七行代码即可比较我们的句子。

更复杂——Transformers和PyTorch

在进入第二种方法之前,值得注意的是它和第一种方法做的是一样的——但在更低的一级上。

通过这种方法,我们需要对_last_hidden_state_执行自己的转换以创建句子嵌入。为此,我们执行平均池化操作。

此外,在平均池化操作之前,我们需要创建_last_hidden_state_,我们可以像这样执行:

在我们产生了密集向量embeddings之后,我们需要执行_mean pooling_操作以创建单个向量编码(句子嵌入)。

为了执行这个平均池操作,我们需要将embeddings张量中的每个值乘以其相应的attention_mask值——以便我们忽略非实际标记。一旦我们得到了我们的密集向量,我们可以计算每个向量之间的余弦相似度——这与我们之前使用的逻辑相同:

我们返回几乎相同的结果——唯一的区别是索引为three的余弦相似度从0.5547变为0.5548——由于四舍五入而产生的微小差异。

这就是使用BERT测量句子语义相似性的介绍——使用_sentence-transformers_和_PyTorch_和_transformers_的低级实现。

你可以在这里这里找到两种方法的完整笔记本。

希望你喜欢这篇文章。如果你有任何问题或建议,请通过Twitter或下面的评论告诉我。如果你对此类内容感兴趣,我也会在YouTube上发布。

感谢你的阅读!

参考资料

N. Reimers,I. Gurevych,Sentence-BERT:使用Siamese BERT-Networks的句子嵌入 (2019),2019年自然语言处理实验方法会议论文集

🤖 NLP With Transformers 课程

如果你想了解更多关于NLP相似度度量(包括我们在此处使用的余弦相似度)的知识,请查看我撰写的解释最流行的度量方法的文章:

NLP中的相似性度量

  • 所有图片均由作者制作,除非另有说明

译自:https://towardsdatascience.com/bert-for-measuring-text-similarity-eec91c6bf9e1

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
alivne
复杂的问题简单化

评论(0)

添加评论