背景
One Hot Encoding和Word Embedding是自然语言处理中最流行的两种向量表示形式。要先理解Word Embedding,我们首先要对One Hot Encoding有所了解,下面我们将进行具体的介绍。
One Hot Encoding
One Hot Encoding,即独热编码,它将原始特征变量转换成以原始特征值分类的多维度变量,并用[0,1]这种方式的新特征值进行替代和量化。
我们可以将每个单词都理解成一个状态,假设存在N个状态,One Hot Encoding的方式就是应用N个状态寄存器对这N个状态进行独立编码,每个状态均由对应的寄存器进行控制,且任意时刻有且仅有一位有效。
举个例子,假设我们现在对cvhub这个单词进行编码,假定单词表的长度为5,即只包含这5个单词,那么编码出来的结果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dKtWXfZl-1679576543760)(null)]
如图所示,独热编码本质上是将输入编码成一个二维的稀疏矩阵,其中对应位置的元素其值置为1,其余位置均为0。显而易见,这种编码方式的优势是计算方便,而劣势则是浪费存储空间,过度占用资源(稀疏编码),容易造成维度灾难。且不同单词之间是彼此独立,缺乏上下文关联的。
Embedding
在正式介绍Word Embedding之前,我们先了解下什么是Embedding。说直白点,Embedding操作就是用一个利用低维向量来表示物体,这个物体可以是一个单词(Word Embedding),一部电影,亦或是一条广告等。Embedding的作用是让具有相似意义的两个物体之间距离更近。
给定一个输入序列[“I”, “love”, “you”],假设词汇表数量为10000个词,如果我们直接应用OHE进行编码,会得到一个极其稀疏的向量化表示,这并不利于基于深度学习技术的应用。若采用词嵌入技术,那么我们除了能够得到一个低维的稠密向量,还能将物体映射成一个实数向量,即采用连续的实数值而非离散的0-1值来表示每个单词的语义。如此一来,具有相似意义的物体便能够通过网络训练,学习出不同物体之间的联系,因此也更加高效。
例如,对于一个N×N的矩阵,假设Embeeding层的维度是N×M,则经过映射后的维度变为N×M,其中M<<N。从某种意义上来说,Embedding层起到了降维的作用,这也是它为什么被叫做嵌入的原因。通过 t-SNE 等降维技术对输出结果进行可视化,我们可以很方便地进行观察。
t-SNE,即t-distributed stochastic neighbor embedding是一种比PCA效果更好的无监督式非线性降维算法,非常适用于高维数据降维到低维数据以进行可视化。
下面,给出一个具体的可视化应用示例:
import matplotlib.pyplot as plt from sklearn.manifold import TSNE from sklearn.decomposition import PCA from sklearn.datasets import load_digits def plot(x_tsne, x_pca, digits): plt.figure(figsize=(12, 8)) plt.subplot(121) plt.scatter(x_tsne[:, 0], x_tsne[:, 1], c=digits.target, label="t-SNE") plt.legend() plt.subplot(122) plt.scatter(x_pca[:, 0], x_pca[:, 1], c=digits.target, label="PCA") plt.legend() plt.show() def main(): digits = load_digits() x_tsne = TSNE(n_components=2, random_state=999).fit_transform(digits.data) x_pca = PCA(n_components=2).fit_transform(digits.data) plot(x_tsne=x_tsne, x_pca=x_pca, digits=digits) if __name__ == '__main__': main()
最后,简单地讲解下Pytorch中所封装好的Embedding层:
import torch embedding = torch.nn.Embedding(num_embeddings=4, embedding_dim=3) words = [ [1, 2], [3, 1] ] embed = embedding(torch.LongTensor(word)) print(embed) print(embed.size()) ------------------output------------------ tensor([[[ 0.0923, -0.0394, 1.0154], [ 0.5492, -1.1071, 0.8220]], [[-0.7135, 0.2804, 0.5426], [ 0.0923, -0.0394, 1.0154]]], grad_fn=<EmbeddingBackward>) torch.Size([2, 2, 3])
这里,num_embeddings代表一共有多少个单词,embedding_dim则表示用一个多少维的向量来表示一个单词。可以看出,对于一个[2, 2]大小的输入序列,经过Embedding层输出后,我们可以得到一个输出维度为[2, 2, 3]的词向量,这里每一个单词均被映射成一个embedding_dim维的向量,即句子中的每一个单词均被表示成一个实数向量。至于embedding_dim的大小如何设置,可以参考这篇文章。除此之外,我们还需要注意Embedding层的参数初始化设置。
Word Embedding
Word Embedding是将输入单词映射成词向量的一种具体技术。Word Embdding方法包括好几种,其中比较有名的时谷歌提出的Word2Vec,其采用了两种模型(CBOW和Skip-gram)以及两种方法(负采样和层次Softmax)的组合:
CBOW:利用周边的上下文信息来预测当中心词;
Skip-gram:通过中心词来预测周边的上下文信息;
Word Embedding一词最早出自于Bengio的论文《Neural Probabilistic Language Models》,而Word2Vec则是谷歌团队提出的一种Word Embedding具体实现方式。
前面我们提到过,独热编码仅仅只是对输入进行独立的编码,每个单词之间彼此互不关联,即不具备上下文联系。然而,在实际的应用场景当中,不同单词之间是存在或多或少的联系的:
时态:如do和did均表达”做“的意思,但一个表示一般式,一个表示过去式,即发生在不同时间段;
语义:如boy和man虽然表达不同的含义,但共性均是表示男性;
单复数:如house和houses分别表示名词的单数和复数形式,这就好比名下有多套房产和仅有1套房差别还是挺大的。
因此,我们希望能够从不同的维度(时态、语义、单复数等)去综合的衡量和表达一个单词的具体含义。这样做的好处具体体现在哪里呢?
从数据层面来说,提高模型精度的两种有效方式无非就是增大数据量或者加入更多有用的先验信息。因此,如果我们想要网络能够更好的理解句子中词与词之间的含义,那么除了增大数据样本外,还可以尝试给网络加入更多的先验信息(Embedding层),让网络能够理解诸如"boy"和"man"之间的共性,又或者理解houses是house的复数形式等。
从模型层面来看的话,假定我们对[“girl”, “woman”, “boy”, “man”]这四个单词进行编码,考虑以下两种不同的表示形式:
One hot representation
每个单词均被视为一个独立的节点输入到网络中进行学习,单词彼此之间并没有关联到,这种通过神经网络硬学习的方式并不能取得很好的效果,因为神经网络很难去学习到它们之间存在什么共性。因此,如果我们能够在输入网络之前加入一些先验信息,那么这将有助于网络更容易收敛。
Distributed representation
这里,我们先梳理下这四个单词之间的联系,根据我们的先验知识,可以得到以下关系表。
如此一来,我们便可以将这四个单词分别编码成向量[[0,1], [0,0], [1,0], [1,1]]。此时,我们便可以将神经网络表示成如下形式。
于是,从这里可以清楚的看出,Embedding层的作用其实就是通过网络学习出一组能够代表先验信息的权重参数。而Word Embedding便是需要从训练数据中自动学习出输入空间到Distributed representation空间的映射f ff。
那么我们又如何能够让网络自动地学习出这种映射关系了。其实可以把嵌入矩阵当成模型参数的一部分,通过大量的语料信息来训练词向量,同时借助不同单词之间的某种联系并结合梯度下降的方法来优化嵌入层的参数,最终获得具有代表性的词向量。
总结
One Hot Encoding是一种将类别型变量向量化的一般做法。它能够简单且快速的创建并更新向量化,只需在向量中添加一个新的项,每一项对应一个新的类别。然而,其编码长度取决于词库的大小,编码后的向量维度很大,很容易造成维度灾难。其次,它也无法体现不同词之间的关联性。
Embedding则是一种需要大量语料进行训练的向量化方法,它所需要的训练时间很长,输出的结果是一组具有固定维度的密集向量。总的来说,独热编码不会告诉我们每个item的具体语义,每一个向量化均是另一个维度的正交表示。Embedding则能够将不同词之间所包含的上下文联系嵌入到词向量表示当中。因此,当我们有充足的训练数据和计算资源,并且有能力应用更复杂的训练算法如Word2Vec或GloVe,那么可以优先选择Embedding技术,否则请直接选择One Hot Encoding即可。
最后,再简单的总结下Word Embedding。在处理NLP任务时,通常需要将输入Sentence中的每个Token进行编码,即得到每个词所对应的词向量,以便后续输入到计算机中利用模型进行训练。Word Embedding是一种将单词从稀疏空间映射到稠密空间技术的统称,它可以将词转化为数值型的词向量,不同词之间的相似性越大,它们之间的距离越小。总的来说,通过Word Embedding,可以将每个词映射到低维的向量空间中,同时还能够保留词本身的所存在的内在信息。