torch.nn.embedding函数的深入解析
- 问题的开端
- 过程解析
- 总结
- 其他
问题的开端
问题的起源从embedding开始,本人并不是以nlp为主,在看过一些论文和书籍后发现embedding有降维功能,但实际操作后,发现torch.nn.embedding这个函数将每一个元素都扩展成了embedding_dim的tensor,那么怎么达到降维的目的呢?根据在网上查到的博客,需要将元素的tensor加起来,才能降维。如果只理解到这里,问题已经解决,但是,该过程是怎么做的,我们不得而知。因此花了一些时间,阅读了torch.nn.embedding函数的源码,来和大家分享,节约下大家宝贵的科研时间。不一定全对,但是希望大家能提出错误并告诉我,我们一起学习。
过程解析
理论上,该过程主要由两条语句构成,分别是:
embedding = nn.Embedding()
out = embedding()
以上两个函数都省略了输入,作用分别对象的创建和调用forward函数,输入参数如下:
(self, num_embeddings, embedding_dim, padding_idx=None,
max_norm=None, norm_type=2., scale_grad_by_freq=False,
sparse=False, _weight=None)
(self, input)
可以看到,embedding对象的创建主要参数有两个,一个num_embeddings,一个是embedding_dim,分别代表嵌入字典的大小以及每个嵌入向量的大小。在源码中,这两个参数其实最重要的作用就是构建一个self.weight矩阵,该矩阵的行数就是num_embeddings,列数就是embedding_dim!由以下代码能看出:
self.weight = Parameter(torch.Tensor(num_embeddings, embedding_dim))
self.reset_parameters()
对于第二个函数,我们进入后,可以得到,他对weight进行了一个填充,约束是均值为0,标准差为1的正态分布,如下:
def normal_(tensor, mean=0., std=1.):
创建完对象后,其实结果的矩阵就已经定了,你得到了一个self.weight矩阵,该矩阵的大小为(num_embeddings,embedding_dim)。或者,你可以自定义self.weight,通过以下代码:
nn.Embedding.from_pretrained()
随后,通过
out = embedding(input)
它调用了forward方法,该方法调用了包下functional的embedding方法:
def forward(self, input):
return F.embedding(
input, self.weight, self.padding_idx, self.max_norm,
self.norm_type, self.scale_grad_by_freq, self.sparse)
最终输入直接对应了获得的self.weight的行数,拿到结果tensor。
总结
该过程主要做了:
1.创建一个embedding对象,该对象中构建一个self.weight矩阵,矩阵的维度是(num_embeddings,embedding_dim),元素符合均值为0,标准差为1的正态分布
2.给出一个输入input,返回self.weight中input行的tensor
其他
本人阅读源码较少,可能有些错误,请大家指出并见谅,感谢各位大佬的阅读。