1、词嵌入
词嵌入(word-embedding)又被称为词向量。
在图像分类中一般使用One-hot编码,比如有五类,如果一个物体属于第二类的话,就可以用编码(0,1,0,0,0)来表示其类别。对于分类问题,十分简单明了。但在自然语言处理中,单词的数目过多,这样做就行不通了。比如有10000个单词,用one-hot方式来定义效率就特别低,每个单词的维度都是10000维的向量,其中只有一个是1,其他的都是0。**特别占内存,除此之外,也不能体现单词的词性。**因为每一个单词都是one-hot。显然有些单词在词义上是相近的,但是one-hot编码无法体现出这种特点。所以必须使用另一种方式定义每一个单词,因此可以引入词嵌入。
词嵌入——对于每一个词而言,可以使用一个高维向量去表示。这里的高维向量和one-hot的区别在于,这个向量不在是0和1的形式,而是向量的每一位都是实数。这个实数则影藏着这个单词的某种 属性,可以通过下面的例子来看。
1、the cat likes playing ball
2、the kitty likes playing wool
3、the dog likes playing ball
4、the boy likes playing ball
重点分析里面的四个词,cat、kitty、dog、boy,如果使用one-hot,那么cat就可以表示成(1,0,0,0),Kitty就可以表示成(0,1,0,0)。但是cat和kitty其实都是表示小猫的意思,所以这两个词语义上是接近的,但是one-hot并不能体现这个特点。
下面用词嵌入来表示这4个词。加入使用二维向量(a,b)来表示一个词,其中a,b分别表示这个词的一种属性,比如a是否喜欢玩球,b是否喜欢玩毛线。并且这个词越大,表示越喜欢,这样就能够定义每个词的嵌入,并且通过这个来区分语义,下面来解释一下原因。
对于cat,可以定义它的词嵌入为(-1,4),因为他不喜欢玩球,喜欢玩毛线。而对于Kitty,它喜欢玩球,可以定义为(-2,5),dog定义为(3,-2),对于boy,他都不喜欢,定义为(-2,-3)。定义好了词嵌入,那么怎么去表示他们之间的相似度呢?可以通过词向量之间的夹角来定义他们的相似度。
下面将每个词向量在坐标系中表示出来,如图所示:
不同向量之间夹角不一样,cat 和kitty夹角比较小,所以他们更加相似,而dog和boy之间夹角比较大,所以他们不相似。
看到这里,我们可以感觉到词嵌入的优势,但是我们也会想到一个问题,对于一个词,我们是如何去定义它的词嵌入,假如向量的维数只有5维,可能还定义的出来,而如果有100维,那怎么定义呢?
这个问题其实不用我们去想,交给神经网络,假如定义100维,神经网络会自己更新每个词嵌入的元素。之前介绍了词嵌入的每个元素都代表一种属性,对于维数比较低的时候,我们可以推断每一维代表的含义,然而维度较高以后,我们不需要关心每一维代表的含义,因为每一维都是网络自己学习出来的属性,只需要知道词向量夹角越小,语义之间越相近。类比如利用卷积神经网络分类,提取出的特征图,我们不需要知道提取出来的具体是什么东西,只需要知道抽象特征能够与帮助我们实现分类就可以!
2、词嵌入的pytorch实现
pytorch中词嵌入是通过函数nn.Embedding(m,n)来实现的,其中m表示所有的单词数目,n表示嵌入的维度。举一个例子:
word_to_ix = { 'hello':0,'word':1}
embeds = nn.Embedding(2,5)
hello_idx = torch.LOngTensor([word_to_ix['hello']])
hello_embed = embeds(hello_idx)
print(hello_embed)