Loading...

参考链接


正文

类定义

1
2
3
4
5
class torch.nn.Embedding(num_embeddings, embedding_dim, 
padding_idx=None, max_norm=None, norm_type=2.0, scale_grad_by_freq=False,
sparse=False, _weight=None,
_freeze=False, device=None,
dtype=None)

给一个编号,嵌入层就能返回这个编号对应的嵌入向量,嵌入向量反映了各个编号代表的符号之间的语义关系。

参数

  • num_embeddings (int): 嵌入字典的大小
  • embedding_dim (int): 每个嵌入向量的大小
  • padding_idx (int, 可选): 如果指定,padding_idx处的条目不会贡献梯度;因此,训练期间padding_idx处的嵌入向量不会更新。它保持为固定的“填充”。对于新构建的Embedding,padding_idx处的嵌入向量将默认为全零。
  • max_norm (float, 可选): 如果给定,每个嵌入向量的范数大于max_norm时,将被重新标准化为范数max_norm。
  • norm_type (float, 可选): 用于计算max_norm选项的p-范数的p。默认为2。
  • scale_grad_by_freq (bool, 可选): 如果给定,这将按照小批量中单词的频率的倒数缩放梯度。默认为False。
  • sparse (bool, 可选): 如果为True,权重矩阵的梯度将是一个稀疏张量。

变量

  • weight (Tensor): 模块的可学习权重,形状为(num_embeddings, embedding_dim),从N(0,1)初始化。

形状

  • 输入: (*), 包含要提取索引的任意形状的IntTensor或LongTensor
  • 输出: (*, H), 其中 * 是输入形状,H = embedding_dim

官方解释nn.embedding是什么:

1
2
3
A simple lookup table that stores embeddings of a fixed dictionary and size.

This module is often used to store word embeddings and retrieve them using indices. The input to the module is a list of indices, and the output is the corresponding word embeddings.

什么是simple lookup table?我没有训练过这个东西,到底哪来的word embedding?底下到底是word2vec、GloVe,还是什么pretrained的东西?

答案其实很简单:都不是。实际上就是“随机”。我们再看一次这个文档,实际上,num_embeddings,第一个参数的意思就是,随便给定一个vocabulary size,比方说3,那么nn.Embedding就会帮你准备3个空位。第二个参数embedding_dim会直接帮你决定他帮你准备的随机的representation要有几个dimensions,你比如说5。

那么你可以想成实际上就是这样:

1
2
3
4
5
{
0: [.123123, .123123, .123123, .12312, .123123], # 五个随机的floats来代表0这个token
1: [.456456,.456456,.456456,.456546,.456456,.42342], # 五个随机的floats来代表1这个token
2: [.789789, .987987, .98798, .5789, .7896, .794] # 五个随机的floats来代表2这个token
}

为什么是5个数字呢?因为你embedding_dim设成5,如果你设成384就会有384个随机数字对应到每一个id。


但是我想处理文字,又不是数字 - Tokenizer在干嘛?你可能接下来会感到困惑的点是…可是我想处理文字,又不是数字…所以…其实tokenizer就是在做这件事。假设你想要把"你好吗"这句话拿去配合什么东西训练,那么你就可能会有个tokenizer做这件事:{你: 0, 好:1, 吗:2}。你的文字input经过tokenizer之后就会变成一串数字,比方说"你好好吗吗"就会变成[0, 1, 1, 2, 2],"你吗吗好"就会变成[0,2,2,1]。

然后经过nn.Embedding的时候他就把刚刚的随机数字塞进去。

所以"你好好吗吗"会被转成这样(就只是去查[0, 1, 1, 2, 2]):

1
2
3
4
5
6
7
{
0: [.123123, .123123, .123123, .12312, .123123],
1: [.456456,.456456,.456456,.456546,.456456,.42342],
1: [.456456,.456456,.456456,.456546,.456456,.42342],
1: [.789789, .987987, .98798, .5789, .7896, .794],
1: [.789789, .987987, .98798, .5789, .7896, .794]]
}

"你吗吗好"就会变成(就只是去查[0,2,2,1])(我们这边先不管padding):

1
2
3
4
5
6
{
0: [.123123,.123123, .123123, .12312, .123123],
2: [.789789, .987987, .98798, .5789, .7896, .794],
2: [.789789, .987987, .98798, .5789, .7896, .794],
1: [.456456,.456456,.456456,.456546,.456456,.42342]
]

更新参数:接下来你会有一个task可能是要训练model来分类什么东西,比方说听起来像不像脏话。那么,

1
2
3
4
5
[[.123123, .123123, .123123, .12312, .123123], 
[.456456,.456456,.456456,.456546,.456456,.42342],
[.456456,.456456,.456456,.456546,.456456,.42342],
[.789789, .987987, .98798, .5789, .7896, .794],
[.789789, .987987, .98798, .5789, .7896, .794]]

可能会对应到类别0(不像),

1
2
3
4
5
6
[
[.123123, .123123, .123123, .12312, .123123],
[.789789, .987987, .98798, .5789, .7896, .794],
[.789789, .987987, .98798, .5789, .7896, .794],
[.456456,.456456,.456456,.456546,.456456,.42342]
]

可能会对应到类比1(有点像)等等。


Vocabulary Size的影响:你的第一个参数(num_embeddings)会影响到你有几个place holders可以用。刚刚我们设3,所以只有三个不同的tokens可以用。所以一旦传进去的index超过2(0,1,2三个参数),就会出错(list out of range)。所以大部分的语言模型都会设一个很大的数字,像是80000,再搭配tokenizer。


示例

1
2
3
4
5
# 包含10个尺寸为3的张量的Embedding模块
embedding = nn.Embedding(10, 3)
# 2个样本的批量,每个样本有4个索引
input = torch.LongTensor([[1, 2, 4, 5], [4, 3, 2, 9]])#torch.Size([2, 4])
embedding(input)##torch.Size([2, 4,3])
1
2
3
4
# 带padding_idx的示例
embedding = nn.Embedding(10, 3, padding_idx=0)
input = torch.LongTensor([[0, 2, 0, 5]])#torch.Size([1, 4])
embedding(input)#torch.Size([1, 4],3)