3、pytorch中nn.Embedding原理及使用
3.1 词向量介绍
图像数据表达不需要特殊的编码,并且有天生的顺序性和关联性,近似的数字会被认为是近似的特征。
正如图像是由像素组成,语言是由词或字组成,可以把语言转换为词或字表示的集合。
然而,不同于像素的大小天生具有色彩信息,词的数值大小很难表征词的含义。最初,人们为了方便,采用One-Hot
编码格式。以一个只有10个不同词的语料库为例(这里只是举个例子,一般中文语料库的字平均在8000 ~ 50000,而词则在几十万左右),我们可以用一个10维的向量表示每个词,该向量在词下标位置的值为1,而其他全部为0。示例如下:
第1个词:[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
第2个词:[0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
第3个词:[0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
……
第10个词:[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
-
这种词的表示方法
十分简单,也很容易实现
,解决了分类器难以处理属性(Categorical)数据的问题。 -
它的缺点也很明显:
冗余太多、无法体现词与词之间的关系
。可以看到,这10个词的表示,彼此之间都是相互正交的,即任意两个词之间都不相关,并且任何两个词之间的距离也都是一样的。同时,随着词数的增加,One-Hot向量的维度也会急剧增长,如果有3000个不同的词,那么每个One-Hot词向量都是3000维,而且只有一个位置为1,其余位置都是0,。虽然One-Hot编码格式在传统任务上表现出色,但是由于词的维度太高,应用在深度学习上时,常常出现维度灾难,所以在深度学习中一般采用词向量
的表示形式。
词向量(Word Vector),也被称为词嵌入(Word Embedding),并没有严格统一的定义。从概念上讲,它是指把一个维数为所有词的数量的高维空间(几万个字,几十万个词)嵌入一个维度低得多的连续向量空间(通常是128或256维)中,每个单词或词组被映射为实数域上的向量。
词向量最重要的特征是相似词的词向量距离相近
。每个词的词向量维度都是固定的,每一维都是连续的数。用词向量表示的词,不仅所用维度会变少(由10维变成2维),其中也会包含更合理的语义信息。英文一般是用一个向量表示一个词,也有使用一个向量表示一个字母的情况。中文同样也有一个词或者一个字的词向量表示,与英文采用空格来区分词不同,中文的词与词之间没有间隔,因此如果采用基于词的词向量表示,需要先进行中文分词。
在PyTorch中,针对词向量有一个专门的层nn.Embedding,用来实现词与词向量的映射
。nn.Embedding具有一个权重,形状是(num_words,embedding_dim),例如对10个词,每个词用2维向量表征,对应的权重就是一个10 * 2的矩阵。Embedding的输入形状是N * W,N是batch size,W是序列的长度,输出的形状是N * W * embedding_dim。输入必须是LongTensor,FloatTensor必须通过tensor.long()方法转成LongTensor
。
3.2 nn.Embedding的API解释
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
)
其为一个简单的存储固定大小的词典的嵌入向量的查找表
,意思就是说,给一个编号,嵌入层就能返回这个编号对应的嵌入向量,嵌入向量反映了各个编号代表的符号之间的语义关系。输入为一个编号列表,输出为对应的符号嵌入向量列表。文章来源:https://www.toymoban.com/news/detail-492675.html
参数解释
文章来源地址https://www.toymoban.com/news/detail-492675.html
- num_embeddings (python:int) – 词典的大小尺寸,比如总共出现5000个词,那就输入5000。此时index为(0-4999)
- embedding_dim (python:int) – 嵌入向量的维度,即用多少维来表示一个符号。
- padding_idx (python:int, optional) – 填充id,比如,输入长度为100,但是每次的句子长度并不一样,后面就需要用统一的数字填充,而这里就是指定这个数字,这样,网络在遇到填充id时,就不会计算其与其它符号的相关性。(初始化为0)
- max_norm (python:float, optional) – 最大范数,如果嵌入向量的范数超过了这个界限,就要进行再归一化。
- norm_type (python:float, optional) – 指定利用什么范数计算,并用于对比max_norm,默认为2范数。
- scale_grad_by_freq (boolean, optional) – 根据单词在mini-batch中出现的频率,对梯度进行放缩。默认为False.
- sparse (bool, optional) – 若为True,则与权重矩阵相关的梯度转变为稀疏张量。
3.3 nn.Embedding的使用及理解
import torch
from torch.nn import functional as F
from torch import nn
1、embedding官方示例
# an Embedding module containing 10 tensors of size 3
# 构造一个vocab size=10,每个vocab用3-d向量表示的table
embedding = nn.Embedding(10, 3)
print(embedding.weight)
Parameter containing:
tensor([[ 0.6694, -0.8900, -0.1363],
[ 0.4114, 0.4581, -0.3432],
[ 0.0981, -0.4604, -0.4365],
[-0.2197, 0.0687, 0.8132],
[-0.2669, -0.8082, -0.2576],
[-0.1423, -1.8045, -0.8497],
[ 1.1308, -0.3347, 1.1927],
[-0.4787, -0.3431, -1.1348],
[ 0.3516, 0.1263, -0.8202],
[-0.6134, 0.1587, -0.7071]], requires_grad=True)
print(embedding.weight.shape) # 可以看做每行是一个词汇的向量表示!
torch.Size([10, 3])
input = torch.LongTensor([
[1,2,4,5],
[4,3,2,9]
]) # 表示这批有2个句子,每个句子由4个单词构成
print(input.shape)
torch.Size([2, 4])
output = embedding(input)
# 维度的前两维和input是一致的。可见多了一个第三维,这就是词向量维度。
print(output.shape)
# output = embedding(input)是去embedding.weight中取对应index的词向量!
# 看output的第一行,input处index=1,对应取出weight中index=1的那一行。其实就是按index取词向量!
print(output)
torch.Size([2, 4, 3])
tensor([[[ 0.4114, 0.4581, -0.3432],
[ 0.0981, -0.4604, -0.4365],
[-0.2669, -0.8082, -0.2576],
[-0.1423, -1.8045, -0.8497]],
[[-0.2669, -0.8082, -0.2576],
[-0.2197, 0.0687, 0.8132],
[ 0.0981, -0.4604, -0.4365],
[-0.6134, 0.1587, -0.7071]]], grad_fn=<EmbeddingBackward0>)
2、embedding计算过程
- embedding的前向过程其实是一个索引的(即查表)的过程
- 表的形式是一个矩阵
- matrix.shape: (v, h)
-v: vocabulary size
-h: hidden dimension
- matrix.shape: (v, h)
- 具体的索引过程是通过one hot + 矩阵乘法实现
- input.shape:(b,s)
- b: batch size
- s: seq len
- embedding(input)
- (b,s) ==> (b,s,h)
- 即:(b,s) 和 (v, h) ===》 (b,s,h)
- input.shape:(b,s)
- 表的形式是一个矩阵
# num_classes=vocab size=10
# 进行one-hot变换
input_onehot = F.one_hot(input, num_classes=10)
print(input_onehot.shape) # (b,s,v)
print(input_onehot.dtype)
print(input_onehot)
torch.Size([2, 4, 10])
torch.int64
tensor([[[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0]],
[[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]]])
print(embedding.weight.dtype)
print(embedding.weight.shape) # (v,h)
torch.float32
torch.Size([10, 3])
# one-hot变换后进行矩阵乘法
output = torch.matmul(input_onehot.type(torch.float32),embedding.weight)
# 可以发现得到的结果和output = embedding(input)一致
# 说明其实质就是one hot + 矩阵乘法 进行实现的
print(output) # (b,s,v) @ (v,h) ===》 (b,s,h)
tensor([[[ 0.4114, 0.4581, -0.3432],
[ 0.0981, -0.4604, -0.4365],
[-0.2669, -0.8082, -0.2576],
[-0.1423, -1.8045, -0.8497]],
[[-0.2669, -0.8082, -0.2576],
[-0.2197, 0.0687, 0.8132],
[ 0.0981, -0.4604, -0.4365],
[-0.6134, 0.1587, -0.7071]]], grad_fn=<UnsafeViewBackward0>)
到了这里,关于Pytorch常用的函数(二)pytorch中nn.Embedding原理及使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!