问题描述
我正在阅读“使用 fastai 和 PyTorch 为编码人员进行深度学习”一书。对于 Embedding 模块的作用,我仍然有些困惑。它似乎是一个简短而简单的网络,但我似乎无法理解 Embedding 与没有偏见的 Linear 的不同之处。我知道它做了一些更快的点积计算版本,其中一个矩阵是一个单热编码矩阵,另一个是嵌入矩阵。这样做实际上是为了选择一条数据?请指出我错在哪里。这是书中展示的简单网络之一。
class DotProduct(Module):
def __init__(self,n_users,n_movies,n_factors):
self.user_factors = Embedding(n_users,n_factors)
self.movie_factors = Embedding(n_movies,n_factors)
def forward(self,x):
users = self.user_factors(x[:,0])
movies = self.movie_factors(x[:,1])
return (users * movies).sum(dim=1)
解决方法
嵌入
[...] 嵌入与没有偏差的线性有什么不同。
基本上所有的东西。 torch.nn.Embedding
是一个查找表;本质上与 torch.Tensor
的工作原理相同,但有一些变化(例如可以在指定索引处使用稀疏嵌入或默认值)。
例如:
import torch
embedding = torch.nn.Embedding(3,4)
print(embedding.weight)
print(embedding(torch.tensor([1])))
会输出:
Parameter containing:
tensor([[ 0.1420,-0.1886,0.6524,0.3079],[ 0.2620,0.4661,0.7936,-1.6946],[ 0.0931,0.3512,0.3210,-0.5828]],requires_grad=True)
tensor([[ 0.2620,-1.6946]],grad_fn=<EmbeddingBackward>)
所以我们基本上采用了嵌入的第一行。仅此而已。
在哪里使用?
通常当我们想为每一行编码一些含义(如 word2vec)时(例如,语义上接近的词在欧几里得空间中接近)并可能训练它们
线性
torch.nn.Linear
(无偏差)也是一个 torch.Tensor
(权重)但它对它(和输入)进行操作,本质上是:
output = input.matmul(weight.t())
每次调用图层时(参见 source code 和 functional definition of this layer)。
代码片段
您的代码片段中的层基本上是这样的:
- 在
__init__
中创建两个查找表 - 使用形状
(batch_size,2)
的输入调用层:- 第一列包含用户嵌入的索引
- 第二列包含电影嵌入的索引
- 将这些嵌入相乘并求和返回
(batch_size,)
(因此它与nn.Linear
不同,后者将返回(batch_size,out_features)
并进行点积而不是像这里这样的逐元素乘法然后求和)
这可能用于训练一些类似推荐系统的表示(用户和电影)。
其他东西
我知道它可以更快地计算点积 其中矩阵之一是one-hot编码矩阵,另一个是 嵌入矩阵。
不,没有。 torch.nn.Embedding
可以是一种热编码,也可以是稀疏的,但取决于算法(以及这些算法是否支持稀疏性),会有或不会有加速。