人类理解语言细微差别的能力是非常强大的——我们敏锐的大脑可以在一句话里轻易地感受到幽默、讽刺、负面情绪等,但发挥这个“超能力”的前提是,我们必须知道话语所使用的语言。

例如,如果有小伙伴用日文评论这篇文章,大部分人应该无法理解他想说什么吧,自然也不敢轻易回复。所以,为了实现有效沟通,我们需要用彼此最能理解的语言进行互动。

而对于机器来说,为了让机器可以处理和理解任意文本,我们必须用机器能够理解的语言来表示文本。那么它最懂哪种语言呢?

答案是数字(numbers)——无论我们提供给机器什么数据:视频、音频、图像或文本,机器都只会与数字打交道,这也就是为什么将文本表示为数字或嵌入文本(embedding text)是自然语言处理中最热门的话题之一。

这篇文章,我将介绍Python代码中最常用的4种句嵌入技术并且概述它们的体系结构以及如何用Python实现这些技术,包括如下内容:什么是词嵌入(Word Embedding)

什么是句嵌入(Sentence Embedding)

Doc2Vec是什么

SentenceBERT介绍

InferSent

Universal Sentence Encoder

什么是词嵌入?

最初的嵌入技术只处理单词,即给定一组单词,而该技术就是把集合中的每个单词生成一个嵌入。最原始的方法是对单词序列进行热编码,如此一来,集合中的单词就由1表示,其他单词由0表示。

虽然这种方法在表示单词和其他简单的文本处理任务上很有效,但面对更复杂的任务(查找相似单词)时却没什么用了。比如,我们需要查询:“北京最好的日料店”,我们希望得到与“日料”、“北京餐厅”和“最好”相对应的搜索结果,若我们得到的结果是“北京的顶级日本料理“,那么用原始方法就无法检测出“最好”和“顶级”,或“料理”和“店”之间的相似性了。词嵌入技术图示

这个词关联问题让词嵌入技术得以开发和发展,与传统的热编码相比,词嵌入技术转换的不仅是单词,还能识别出该词的语义和语法以构建该信息的向量。目前常用的词嵌入技术有Word2Vec、GloVe、ELMo、FastText等。

词嵌入的基本原理就是使用与该词相邻的词的信息。随着词嵌入技术的发展,技术人员已经找到了更好的方法来表达更多的信息,由此扩展到了句子和段落。

什么是句嵌入?

如果我们直接处理句子呢?要知道,在大文本的情况下,很大程度上我们的分析会被从词嵌入中提取的信息所限制。

假设,我们读到一个句子“我不喜欢拥挤的地方”,接着,我们又读到“然而,我喜欢世界上最繁忙的城市之一,纽约”。我们怎样才能让机器明白“拥挤的地方”和“繁忙的城市”之间的关联呢?

显然,词嵌入技术在这里是不够的,我们需要用到句嵌入技术了。句嵌入是将整个句子及其语义信息表示为向量,让机器能理解上下文、用意和其他潜藏在文本中的细微差别。

接下来我们将用Python代码实例,直观地给大家介绍目前最受欢迎的4中句嵌入技术:Doc2Vec、SentenceBERT、InferSent、Universal Sentence Encoder

那我们一起来建立基本语料库并定义句子列表吧!

Step 1:

首先,导入库并下载‘punkt’

import nltk

nltk.download('punkt')

from nltk.tokenize import word_tokenize

import numpy as np

Step 2:

然后,我们来定义句子列表。当然,你也可以使用一个更大的列表(最好只使用一个句子列表以便更容易地处理每个句子)

sentences = ["I ate dinner.",

"We had a three-course meal.",

"Brad came to dinner with us.",

"He loves fish tacos.",

"In the end, we all felt like we ate too much.",

"We all agreed; it was a magnificent evening."]

Step 3:

我们再保留一份这些句子的标记版

# Tokenization of each document

tokenized_sent = []

for s in sentences:

tokenized_sent.append(word_tokenize(s.lower()))

tokenized_sent

Step 4:

最后,我们定义一个函数,让它返回两个向量间的余弦相似度(cosine similarity)

def cosine(u, v):

return np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v))

好了!接下来,我们就用这个句子列表来学习这4个句嵌入技术吧!

Doc2Vec

作为Word2Vec的扩展,Doc2Vec是当下最流行的句嵌入技术之一。该算法于2014年引入,是一种无监督算法,主要原理是将一个“段落向量”添加到Word2Vec模型中,而其中,添加方法两个:

1) PVDM(分布式存储版本的段落向量):

在分配一个段落向量句的同时给所有句子共享词向量。然后通过平均或连接(段落向量和单词向量)来得到最后的句关联。其实,它是Word2Vec连续词袋法的扩展——在词袋中,我们根据一组单词预测下一个单词。在PVDM中,我们是根据一组句子预测下一个句子。PVDM图示

2) PVDOBW(分布式包词版本的段落向量):

和PVDM一样, PVDOBW也是Word2Vec的另一扩展,但与PVDM不同的是,我们只在句子中随机抽取单词,然后让模型去预测它来自哪个句子(可以理解成是一个分类任务)。

Step 1:

我们将使用Gensim来演示如何使用Doc2Vec。首先要导入模型、语料库和其他库,然后构建一个带标记的语料库。每个句子都被表示为一个TaggedDocument,其中包含单词列表和与之关联的标记。

# import

from gensim.models.doc2vec import Doc2Vec, TaggedDocument

tagged_data = [TaggedDocument(d, [i]) for i, d in enumerate(tokenized_sent)]

tagged_data

Step 2:

接着,我们将用以下参数对模型进行训练:

## Train doc2vec model

model = Doc2Vec(tagged_data, vector_size = 20, window = 2, min_count = 1, epochs = 100)

'''

vector_size = Dimensionality of the feature vectors.

window = The maximum distance between the current and predicted word within a sentence.

min_count = Ignores all words with total frequency lower than this.

alpha = The initial learning rate.

'''

## Print model vocabulary

model.wv.vocab

Step 3:

我们现在来挑一个句子来测试吧,让模型去从数据中找出与其最相似的5个句子,并按相似度降序显示。其中,infer_vector方法返回测试句子的向量化形式(包括段落向量);most_similar方法返回相似的句子。

test_doc = word_tokenize("I had pizza and pasta".lower())

test_doc_vector = model.infer_vector(test_doc)

model.docvecs.most_similar(positive = [test_doc_vector])

'''

positive = List of sentences that contribute positively.

'''

成功找到了!

SentenceBERT

SentenceBERT在2018年一经推出就立即在句嵌入测试中受到热捧。这个基于BERT模型的技术有4个关键概念:Attention

Transformer

BERT

孪生神经网络(Siamese Network)

SentenceBERT使用孪生神经网络结构,使用2个句子作为输入。这2个句子会被传递给BERT模型,然后使用pooling层来生成它们的嵌入。最后使用句子对的嵌入作为输入来计算余弦相似度。孪生神经网络图示

SentenceBERT技术图示

Step 1:

加载预训练的BERT模型。sentence-transformers里还有许多其他开源的预训练模型,可以在此处找到模型的完整列表。

!pip install sentence-transformers

from sentence_transformers import SentenceTransformer

sbert_model = SentenceTransformer('bert-base-nli-mean-tokens')

Step 2:

对句子进行编码并显示句子向量:

sentence_embeddings = model.encode(sentences)

#print('Sample BERT embedding vector - length', len(sentence_embeddings[0]))

#print('Sample BERT embedding vector - note includes negative values', sentence_embeddings[0])

Step 3:

定义一个测试查询并对其进行编码:

query = "I had pizza and pasta"

query_vec = model.encode([query])[0]

Step 4:

使用scipy计算余弦相似度,然后检索句子和测试查询间的相似度

for sent in sentences:

sim = cosine(query_vec, model.encode([sent])[0])

print("Sentence = ", sent, "; similarity = ", sim):

我们获得文本中的句子与测试句之间的相似性了!实例使用的是已经预训练的BERT模型,如果小伙伴想从头训练SentenceBERT,它的运行速度将会变得异常慢hhh。

InferSent

InferSent是Facebook人工智能研究所在2018年推出的一项有监督的句嵌入技术。该模型最大的特点是它是在自然语言推理(NLI)数据集里训练的,更具体地说,就是SNLI (Stanford自然语言推理)数据集。该数据集由57万对人类生成的英语句子组成,而这些句子已经被人工标记为隐含、矛盾或中性了。

和SentenceBERT一样,InferSent也是使用一对句子并对它们进行编码以生成实际的句子嵌入:

输出向量进入分类器,分类器会将向量分类到3个定义类别之一中(concatenation、element-wise product、absolute element-wise difference)

让我们看看句子相似度任务是如何使用推理的。我们将使用PyTorch进行此操作:

Step 1:

首先,下载推断模型和已经预训练的单词向量。为此,请从这里保存model .py文件并将其存储到工作目录中。

我们还需要保存训练好的模型和预训练好的GLoVe词向量。所以,我们的工作目录应该有一个“encoders”文件夹和一个名为“GLoVe”的文件夹。encoders文件夹将有我们的模型,而GloVe文件夹应该有词向量:

! mkdir encoder

! curl -Lo encoder/infersent2.pkl https://dl.fbaipublicfiles.com/infersent/infersent2.pkl

! mkdir GloVe

! curl -Lo GloVe/glove.840B.300d.zip http://nlp.stanford.edu/data/glove.840B.300d.zip

! unzip GloVe/glove.840B.300d.zip -d GloVe/

加载模型和词向量:

from models import InferSent

import torch

V = 2

MODEL_PATH = 'encoder/infersent%s.pkl' % V

params_model = {'bsize': 64, 'word_emb_dim': 300, 'enc_lstm_dim': 2048,

'pool_type': 'max', 'dpout_model': 0.0, 'version': V}

model = InferSent(params_model)

model.load_state_dict(torch.load(MODEL_PATH))

W2V_PATH = '/content/GloVe/glove.840B.300d.txt'

model.set_w2v_path(W2V_PATH)

Step 2:

从最开始准备好的句子列表中构建词汇表:

model.build_vocab(sentences, tokenize=True)

Step 3:

测试——使用InferSent对该测试查询进行编码并生成嵌入:

query = "I had pizza and pasta"

query_vec = model.encode(query)[0]

query_vec

Step 4:

计算此查询与文本中每个句子的余弦相似度:

similarity = []

for sent in sentences:

sim = cosine(query_vec, model.encode([sent])[0])

print("Sentence = ", sent, "; similarity = ", sim)

Universal Sentence Encoder

目前性能最好的句嵌入技术应该就是Universal Sentence Encoder了,是我们可以用它来进行多任务学习。

这意味着我们生成的句嵌入可以用于多种任务,如情绪分析、文本分类、句子相似度等,这些请求的结果会反馈到模型中,从而得到比之前更好的句向量。

Universal Sentence Encoder是基于两种编码器的模型:Transformer和Deep Averaging Network(DAN)这两种模型都能够将一个单词或句子作为输入,并为其生成嵌入。基本流程如下:将句子转换为小写字母后将其标记

根据编码器的类型,句子被转换为512维向量如果我们使用Transformer,它类似于transformer模块的架构,会使用自注意机制。

使用DAN则会首先计算unigram和bigram嵌入,然后对它们进行平均以得到单个嵌入。然后,它被传递到深度神经网络,以得到512维的句嵌入。

这些句嵌入然后用于各种非监督和监督任务,如Skipthoughts, NLI等,然后再次重用训练好的模型,生成新的512维句子嵌入。

首先下载TensorFlow and TensorFlow hub:

!pip3 install --upgrade tensorflow-gpu

# Install TF-Hub.

!pip3 install tensorflow-hub

Step 1:

导入需要的库:

import tensorflow as tf

import tensorflow_hub as hub

import numpy as np

Step 2:

通过TFHub使用该模型:

module_url = "https://tfhub.dev/google/universal-sentence-encoder/4"

model = hub.load(module_url)

print ("module %s loaded" % module_url)

Step 3:

为句子列表和查询生成嵌入:

sentence_embeddings = model(sentences)

query = "I had pizza and pasta"

query_vec = model([query])[0]

Step 4:

计算测试查询与句子列表之间的相似度:

for sent in sentences:

sim = cosine(query_vec, model([sent])[0])

print("Sentence = ", sent, "; similarity = ", sim)

小结

小编给大家介绍了自然语言处理中中最常用的4种句嵌入技术以及用于查找文本相似度的基本代码。这里小编建议大家使用更大的数据集来尝试这些模型。此外,这里只提供了计算句子相似度的基本代码。对于其他适合的模型,您需要首先对这些句子进行预处理,然后将它们转换为嵌入。

此外,小编这里并没有说没有其他流行的模式(包括FastSent, Skip-thought, Quick-thought, Word Movers Embedding等)

如果你已经尝试过这些或任何其他模式,请在评论中与我们分享!

欢迎点赞、收藏、留言!【自然语言处理】学习帐​www.zhihu.com

python词嵌入_【自然语言处理】收藏!使用Python的4种句嵌入技术相关推荐

  1. 如何用python做词云图_科学网—如何用Python做词云?(基础篇视频教程) - 王树义的博文...

    只需要花10几分钟,跟着教程完整做一遍,你就能自己用Python做出词云了. <如何用Python做词云?>图文版发布于2017年6月,是我数据科学系列教程中的第一篇. 目前仅简书一个平台 ...

  2. 怎么用python自制计算公式_手把手教你用python制作简易计算器,能够记录你使用的情况...

    话不多说,首先先看效果图,它能够记录你在使用过程中的历史,方便你查看是否有错: 接下来就仔细分析一下是如何制作的: 简易计算器 第一步:导入资源库 在过程中使用到了tkinter这个资源库,win+R ...

  3. python做运动控制_第一课:用Python操控小龟小车运动

    欢迎来到小龟的课堂,今天我们讲如何用小龟小车的车载Python控制小车运动. 如果小伙伴还不会使用小龟小车的Python编辑器的话,可以阅读这篇教程<如何使用小龟小车的Python编辑器> ...

  4. python计算学习_跟老齐学Python之用Python计算

    一提到计算机,当然现在更多人把她叫做电脑,这两个词都是指computer.不管什么,只要提到她,普遍都会想到她能够比较快地做加减乘除,甚至乘方开方等.乃至于,有的人在口语中区分不开计算机和计算器. 那 ...

  5. print python excel分隔_合并/拆分 Excel?Python、VBA轻松自动化

    作者 | Ryoko 来源 | 凹凸数据 当你收集了 n 个人的 EXCEL 记录表,需要将它们汇成一个总表时你会怎么做呢? 如果不通过技术手段,要一个个打开再复制粘贴也太麻烦了吧! 此时就需要一个通 ...

  6. python医学应用_数据分析工具鄙视链:Python、R语言是老大,Excel只能称小弟?

    最新行业报告 2020数据分析.商业分析行业报告工作岗位与职能.薪资对比.热招公司等多方面详细解读帮助你一网打尽,斩获心仪Offer! 扫码回复[数据分析 0]立即领取 History语言发展史ABC ...

  7. python数据结构题目_《数据结构与算法Python语言描述》习题第二章第三题(python版)...

    ADT Rational: #定义有理数的抽象数据类型 Rational(self, int num, int den) #构造有理数num/den +(self, Rational r2) #求出本 ...

  8. python 简历处理_按照这个方式学Python,老板把垃圾桶里的简历舔回来:月薪50000...

    对于Python相信很多人都不陌生,相较于Excel.Tableau.PowerBI等普通的数据分析工具来说,Python的优势显然要大很多.Python有很多优点,如果你能很好的运用到工作中,会发现 ...

  9. python的精髓_教你玩转Python!一文总结Python入门到精髓的窍门

    (建议收藏) 很多人应该都有过这种经历,大量重复性工作:日报.周报.各种报,无穷无尽:不计其数的数据提取······琐碎繁杂的事务让工作的效率极低.如果可以一键完成就好了. 对这些问题来说,最高效的解 ...

最新文章

  1. ModuleNotFoundError: No module named ‘scipy.spatial.transform._rotation_groups‘
  2. K8s中的external-traffic-policy是什么?
  3. Harbor: 跨数据中心复制Docker镜像的开源实现
  4. 传输层 :TCP/UDP 协议(用于封装接口)
  5. 从CMDB动态获取服务器列表,按照Ansible的约定
  6. mysql怎么获取系统_MySQL获取系统性能和状态代码
  7. 使用ESXi-Customizer为esxi注入第三方驱动
  8. c语言在线电子词典的实验报告,电子词典系统设计实验报告.doc
  9. BinaryViewer(二进制查看器)使用教程(附下载)
  10. 【流媒体开发】6、ffplay命令
  11. 公用计算机不使用键盘鼠标,鼠标键盘同时不能用了怎么回事_电脑的键盘和鼠标不能同时用如何解决...
  12. pc端js获取当前经纬度_js获取用户当前地理位置(省、市、经纬度)
  13. 【c#技术】一篇文章搞掂:水晶报表
  14. 【收藏】亲测奥维互动地图如何导入2023谷歌地图
  15. java实现OCR图文识别Tess4j,高准确率高效率
  16. 微信小程序获取urlScheme地址Python版
  17. ChatGPT修bug横扫全场,准确率达78%!程序员喜忧参半
  18. iOS 使用UIBezierPath类实现随手画画板
  19. 头条号《群媒体》,自媒体工作室必看
  20. 计算机操作系统虚拟内存管理

热门文章

  1. 接口可以继承多个接口总结
  2. OpenLDAP(2.4.3x)服务器搭建及配置说明
  3. 【致青春】我们挥霍时间的年代
  4. hdu 1497(图书管理系统模拟)
  5. 在fedora linux中,wine 成功安装手记
  6. 数据结构与算法之-----栈的应用(二)
  7. html标签非成对,深入document.write()与HTML4.01的非成对标签的详解
  8. c语言成绩统计与学籍管理源码,[源码和文档分享]基于C语言的学生成绩管理系统...
  9. 大专java考试试题_专科—程序设计基础题库-java.doc
  10. 互联网产品开发中的“快”字诀