作者:top_小酱油
链接:https://www.jianshu.com/p/63e7acc5e890
来源:简书
内容:上述是以RNN为基础解析的
该方法定义了一个简单的存储固定大小的词典的嵌入向量的查找表,意思就是说,这就是一个词典,里面包含了各个单词的向量,如果要访问该查找表,需要你给定一个编号,嵌入层就能返回这个编号对应的嵌入向量,嵌入向量反映了各个编号代表的符号之间的语义关系。
注意这里是定义的查找表! 如果要访问还需要后面的操作! 也就是先定义后操作!
当在访问该查找表的时候:
输入为一个编号列表,输出为对应的符号嵌入向量列表。
shape:
~Embedding.weight (Tensor) –形状为 (num_embeddings, embedding_dim) 的学习权重采用标准正态分布N(0,1)进行初始化
请记住,只有有限数量的优化器支持稀疏梯度:目前是optim.SGD(CUDA和CPU), optim.SparseAdam (CUDA和CPU)和optim.Adagrad (CPU)
当max_norm≠None时,Embedding的前向方法将就地修改权重张量。由于梯度计算所需的张量不能被就地修改,所以在Embedding上执行可微运算。在调用Embedding的前向方法之前,需要克隆Embedding。max_norm不是None时的权重。例如:
n, d, m = 3, 5, 7
embedding = nn.Embedding(n, d, max_norm=True)
W = torch.randn((m, d), requires_grad=True)
idx = torch.tensor([1, 2])
a = embedding.weight.clone() @ W.t() # weight must be cloned for this to be differentiable
b = embedding(idx) @ W.t() # modifies weight in-place(就地修改权重)
out = (a.unsqueeze(0) + b.unsqueeze(1))
loss = out.sigmoid().prod()
loss.backward()
实际上,Embedding通过随机初始化建立了词向量层后,建立了一个“二维表”,存储了词典中每个词的词向量。每个mini-batch的训练,都要从词向量表找到mini-batch对应的单词的词向量作为模型的输入放进网络。
>>> # an Embedding module 包含了10个张量,每个张量的大小为3
>>> embedding = nn.Embedding(10, 3)
>>> # a batch 含有两个样本,每个样本长度为4,也就是四个索引,索引是词典中的index序号
>>> input = torch.LongTensor([[1,2,4,5],[4,3,2,9]])
>>> embedding(input)
tensor([[[-0.0251, -1.6902, 0.7172],
[-0.6431, 0.0748, 0.6969],
[ 1.4970, 1.3448, -0.9685],
[-0.3677, -2.7265, -0.1685]],
[[ 1.4970, 1.3448, -0.9685],
[ 0.4362, -0.4004, 0.9400],
[-0.6431, 0.0748, 0.6969],
[ 0.9124, -2.3616, 1.1151]]])
>>> # example with padding_idx
>>> embedding = nn.Embedding(10, 3, padding_idx=0)
>>> input = torch.LongTensor([[0,2,0,5]])
>>> embedding(input)
tensor([[[ 0.0000, 0.0000, 0.0000],
[ 0.1535, -2.0309, 0.9315],
[ 0.0000, 0.0000, 0.0000],
[-0.1655, 0.9897, 0.0635]]])
>>> # example of changing `pad` vector
>>> padding_idx = 0
>>> embedding = nn.Embedding(3, 3, padding_idx=padding_idx)
>>> embedding.weight
Parameter containing:
tensor([[ 0.0000, 0.0000, 0.0000],
[-0.7895, -0.7089, -0.0364],
[ 0.6778, 0.5803, 0.2678]], requires_grad=True)
>>> with torch.no_grad():
... embedding.weight[padding_idx] = torch.ones(3)
>>> embedding.weight
Parameter containing:
tensor([[ 1.0000, 1.0000, 1.0000],
[-0.7895, -0.7089, -0.0364],
[ 0.6778, 0.5803, 0.2678]], requires_grad=True)
和上面的使用是类似的,也是定义一个查找表!
从给定的2维FloatTensor创建嵌入实例。
参数:
>>> # FloatTensor containing pretrained weights
>>> weight = torch.FloatTensor([[1, 2.3, 3], [4, 5.1, 6.3]])
>>> embedding = nn.Embedding.from_pretrained(weight)
>>> # Get embeddings for index 1
>>> input = torch.LongTensor([1])
>>> embedding(input)
tensor([[ 4.0000, 5.1000, 6.3000]])
实际代码举例:
if pretrained_word_embedding is None: #如果没有预训练词典,那么就用第一个
self.word_embedding = nn.Embedding(config.num_words,
config.word_embedding_dim,
padding_idx=0)
else: #我们就用预训练的词典
self.word_embedding = nn.Embedding.from_pretrained(
pretrained_word_embedding, freeze=False, padding_idx=0)
if pretrained_entity_embedding is None:
self.entity_embedding = nn.Embedding(config.num_entities,
config.entity_embedding_dim,
padding_idx=0)
else: #实体的嵌入也是一样的,同上
self.entity_embedding = nn.Embedding.from_pretrained(
pretrained_entity_embedding, freeze=False, padding_idx=0)
if config.use_context: #上下文嵌入也是一样的,同上
if pretrained_context_embedding is None:
self.context_embedding = nn.Embedding(
config.num_entities,
config.entity_embedding_dim,
padding_idx=0)
else:
self.context_embedding = nn.Embedding.from_pretrained(
pretrained_context_embedding, freeze=False, padding_idx=0)