通俗讲解pytorch中nn.Embedding原理及使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通俗讲解pytorch中nn.Embedding原理及使用相关的知识,希望对你有一定的参考价值。

参考技术A

其为一个简单的存储固定大小的词典的嵌入向量的查找表,意思就是说,给一个编号,嵌入层就能返回这个编号对应的嵌入向量,嵌入向量反映了各个编号代表的符号之间的语义关系。

输入为一个编号列表,输出为对应的符号嵌入向量列表。

torch.nn包下的Embedding,作为训练的一层,随模型训练得到适合的词向量。

找到对应的词向量放进网络:词向量的输入应该是什么样子

实际上,上面通过随机初始化建立了词向量层后,建立了一个“二维表”,存储了词典中每个词的词向量。每个mini-batch的训练,都要从词向量表找到mini-batch对应的单词的词向量作为RNN的输入放进网络。那么怎么把mini-batch中的每个句子的所有单词的词向量找出来放进网络呢, 输入是什么样子,输出是什么样子?

首先我们知道肯定先要建立一个词典,建立词典的时候都会建立一个dict:word2id:存储单词到词典序号的映射。假设一个mini-batch如下所示:

显然,这个mini-batch有3个句子,即batch_size=3

第一步首先要做的是:将句子标准化,所谓标准化,指的是:大写转小写,标点分离,这部分很简单就略过。经处理后,mini-batch变为:

可见,这个list的元素成了一个个list。还要做一步:将上面的三个list按单词数从多到少排列。标点也算单词。至于为什么,后面会说到。

那就变成了:

可见,每个句子的长度,即每个内层list的元素数为:5,5,4。这个长度也要记录。

之后,为了能够处理,将batch的单词表示转为在词典中的index序号,这就是word2id的作用。转换过程很简单,假设转换之后的结果如下所示,当然这些序号是我编的。

同时,每个句子结尾要加EOS,假设EOS在词典中的index是1。

那么长度要更新:

很显然,这个mini-batch中的句子长度 不一致! 所以为了规整的处理,对长度不足的句子,进行填充。填充PAD假设序号是2,填充之后为:

这样就可以直接取词向量训练了吗?

不能!上面batch有3个样例,RNN的每一步要输入每个样例的一个单词,一次输入batch_size个样例,所以batch要按list外层是时间步数(即序列长度),list内层是batch_size排列。即batch的维度应该是:

重要的问题说3遍!

怎么变换呢?变换方法可以是:使用itertools模块的zip_longest函数。而且,使用这个函数,连填充这一步都可以省略,因为这个函数可以实现填充!

经变换,结果应该是:

记得我们还记录了一个lens:

batch还要转成LongTensor:

这里的batch就是词向量层的输入。

词向量层的输出是什么样的?

好了,现在使用建立了的embedding直接通过batch取词向量了,如:

假设词向量维度是6,结果是:

维度的前两维和前面讲的是一致的。可见多了一个第三维,这就是词向量维度。所以,Embedding层的输出是:

每天讲解一点PyTorch nn.Embedding

今天我们讲解创建词嵌入模型
nn.Embedding(5, 6)
代表5个词(总共有多少个词)6维度(每个词的编码维度),5x6矩阵

>>> import torch
>>> import torch.nn as nn
>>> 
>>> embeds = nn.Embedding(5, 6)
>>> embeds
Embedding(5, 6)
>>> 
>>> import torch
>>> import torch.nn as nn
>>> 
>>> embeds = nn.Embedding(5, 6)
>>> embeds
Embedding(5, 6)
>>> # I like cv
>>> # 1 2 3
>>> word = [[1,2,3],[0,0,3]]
>>> x = torch.LongTensor(word)
>>> x
tensor([[1, 2, 3],
        [0, 0, 3]])

>>> embed_ = embeds(torch.LongTensor(word))
>>> 
>>> embed_
tensor([[[ 1.1774,  0.0840,  1.2077,  0.3492, -0.1718, -0.2256],
         [-1.1595,  0.2247,  0.8931, -0.6904, -0.3020, -0.4171],
         [-2.2413,  0.3168, -0.1047,  0.8574, -0.2742,  0.1194]],

        [[ 1.7274,  0.9688, -1.2030,  1.0693, -0.5663,  1.8714],
         [ 1.7274,  0.9688, -1.2030,  1.0693, -0.5663,  1.8714],
         [-2.2413,  0.3168, -0.1047,  0.8574, -0.2742,  0.1194]]],
       grad_fn=<EmbeddingBackward>)
>>> embed_.shape
torch.Size([2, 3, 6])
>>> 

输入维度:2x3的词
每个词编码:6维度向量

>>> word = [1,2,3]
>>> word
[1, 2, 3]
>>> embed_ = embeds(torch.LongTensor(word))
>>> embed_
tensor([[ 1.1774,  0.0840,  1.2077,  0.3492, -0.1718, -0.2256],
        [-1.1595,  0.2247,  0.8931, -0.6904, -0.3020, -0.4171],
        [-2.2413,  0.3168, -0.1047,  0.8574, -0.2742,  0.1194]],
       grad_fn=<EmbeddingBackward>)
>>> 
>>> embed_.shape
torch.Size([3, 6])
>>> 

输入维度:3的词
每个词编码:6维度向量

>>> embeds = nn.Embedding(4, 6)
>>> embeds
Embedding(4, 6)
>>> word
[1, 2, 3]
>>> x = torch.LongTensor(word)
>>> x
tensor([1, 2, 3])
>>> 
>>> embed_ = embeds(x)
>>> embed_
tensor([[ 1.8449,  0.3119, -0.0317, -0.7793, -0.6710,  0.0316],
        [ 0.8638, -1.2257,  0.5386, -0.6412,  1.4129,  0.0926],
        [ 0.5742,  1.2701,  0.3415,  0.3161, -1.7954,  0.8924]],
       grad_fn=<EmbeddingBackward>)
>>> 
>>> embeds = nn.Embedding(len("0123456789"), 6)
>>> embeds
Embedding(10, 6)
>>> 

以上是关于通俗讲解pytorch中nn.Embedding原理及使用的主要内容,如果未能解决你的问题,请参考以下文章

每天讲解一点PyTorch nn.Embedding

PyTorch之 torch.nn.Embedding 词嵌入层的理解

深入理解PyTorch中的nn.Embedding

pytorch中,嵌入层torch.nn.embedding的计算方式

pytorch中nn.Embedding原理及使用

PyTorch:Embedding初始化及自定义