美文网首页
2023-08-24 02 nn.Embedding

2023-08-24 02 nn.Embedding

作者: 麒麟楚庄王 | 来源:发表于2023-08-23 17:24 被阅读0次

1. nn.Embedding的位置参数

官方文档 Embedding — PyTorch 2.0 documentation

以下正文来源于 关于nn.Embedding的解释,以及它是如何将一句话变成vector的_迷茫终会遇见光的博客-CSDN博客

nn.Embedding((num_embeddings,embedding_dim)

num_embeddings代表词典大小尺寸,int型,比如训练时所可能出现的词语一共50000个词,那么就有num_embedding=50000

embedding_dim表示嵌入向量的维度,int型,具体含义我们下面来解释。

2. embedding_dim的初步解释

现在有一句话(这句话有length个字),如果用one-hot的方式来编码,那我们需要一个(length,50000)的矩阵代表这句话。

那我们现在想用embedding方法来表示,我们指定一个embedding_dim,embedding_dim<50000。

也就是说,我们一共需要(length,embedding_dim)的矩阵代表这句话。相当于(length,50000)*(50000,embedding),做了个矩阵运算。

3. embedding_dim的举例说明

为了方便计算,我们将句子的最大长度设置为max_length (输入模型的所有语句不可能超过这个长度。)

当整个输入数据X只有一句话时  X(1, max_length, num_embeddings)

而字典为(num_embeddings, embedding_dim)

则经过字典翻译之后,这句话变成(1,max_length,embedding_dim)

当输入数据X有多句话时,即Batch_size不等于1,有X(batch_size, max_length, num_embeddings)

字典为仍然为(num_embeddings, embedding_dim)

则经过字典翻译之后,输入数据X变成(batch_size,max_length,embedding_dim)

— — — — — — — — 总结一下— — — — — — — —

nn.embedding(num_embeddings,embedding_dim)的作用就是将输入数据降维到embedding_dim的表示层上,得到了输入数据的另一种表现形式。

在GRU等模型的输入中,可认为是input_size

— — — — — — — — 举个例子— — — — — — — —

import torch.nn as nn

num_embeddings= 4 #词典长度

embedding_dim= 2

embed = nn.Embedding(num_embeddings,embedding_dim)

x = torch.LongTensor([[0,1,2],[3,2,1]])

x_embed = embed(x)

print(x_embed.size()) # torch.Size([2, 3, 2]) 即(batch_size,max_length,embedding_dim)

print(x_embed)结果如下:

— — — — — — 

tensor([[[-0.0256, -0.2226],

        [-0.5378, -0.1191],

        [ 0.1259, -1.6695]],

        [[ 0.6608, -0.7670],

        [ 0.1259, -1.6695],

        [-0.5378, -0.1191]]], grad_fn=<EmbeddingBackward0>)

— — — — — — 

使用embedding去发现词隐藏的特征形式,使用神经网络的方法去自行学习?

— — — — — — — — 注意事项— — — — — — — —

num_embeddings表示嵌入的字典个数,如果输入的的是数组,那么num_embeddings至少要比数组中最大的元素要大

否则,会出现IndexError: index out of range in self

比如你的字典50000个词,你来一个输入是50009,这就是超出词典范围了!!!

4. 关于 输入<num_embeddings 的要求

例子来源于nn.Embedding的使用_nn.embedding的输入输出_YoJayC的博客-CSDN博客

— — — — — — — — 第一个位置参数num_embeddings — — — — — — — —

# embedding = nn.Embedding(10, 3) # num_embeddings,这里是10,至少要比输入元素中最大值要大

embedding = nn.Embedding(8, 4) # num_embeddings,这里是8

inputs = torch.LongTensor([[1, 2, 4, 5], [4, 3, 2, 9]])

print(inputs.shape)

outputs = embedding(inputs)

print(outputs.shape)

在上面的代码中,输入数组的最大元素是9。

当设置nn.Embedding(10, 3) 时,能够正常运行,得到输出

torch.Size([2, 4])

torch.Size([2, 4, 3])

当设置nn.Embedding(8, 4)时,报错IndexError: index out of range in self。

— — — — — — — — 第二个位置参数embedding_dim— — — — — — — —

第二个参数embedding_dim表示每一个嵌入向量的大小。

nn.Embedding的输入只能是LongTensor,大小为 (batch_size, sequence_length)

输出的大小为 (batch_size, sequence_length, embedding_dim),即输出在输入后增加了隐藏层的维度

5.  关于Embedding的weight

以下是参考torch.nn.Embedding()详解_Quinn-ntmy的博客-CSDN博客

我们还是继续来看4给出的例子的前半段

— — — — — — — — Embedding.weight为 可学习参数— — — — — — — —

import torch.nn as nn

num_embeddings= 4 #词典长度

embedding_dim= 2

embed = nn.Embedding(num_embeddings,embedding_dim)

print(embed.weight)

— — — — — —  这时我们得到输出:

Parameter containing:

tensor([[-0.2238, -0.5062],

        [-1.2614,  1.1866],

        [-0.9223, -0.7123],

        [-1.5234, -0.4360]], requires_grad=True)

requires_grad=True,所以weight是可学习的。

— — — — — — — Enbedding Layer是如何初始化权重矩阵(即查找表)的??— — — — — — —

更新weight时主要使用了实例方法self.reset_parameters(),而这个实例方法又调用了初始化(init)模块中的normal_方法。

nn.Embedding对应的源码摘录:

class Embedding(Module):

        ............

        if _weight is None:

            self.weight = Parameter(torch.empty((num_embeddings, embedding_dim), **factory_kwargs))

            self.reset_parameters()

        else:

                ............

    def reset_parameters(self) -> None:

        init.normal_(self.weight)

          ............

————————————————

初始化为标准正态分布(均值为0,标准差是1) ,形状为 (num_embeddings, embedding_dim)

我们也可以自己写代码算下均值和方差

torch.mean(embed.weight)

torch.var(embed.weight)

这里由于设置的形状都比较小,所以乍一算起来与0相差比较远

— — — — — — 

或者也可以用scipy.stats.shapiro可以检测数据是否符合正态分布。

import torch.nn as nn

num_embeddings= 1000 #词典长度

embedding_dim= 5

embed = nn.Embedding(num_embeddings,embedding_dim)

— — — — — — — —

from scipy.stats import shapiro

print('结果:',shapiro(embed.weight.detach().numpy()))

我们得到:

结果: (0.9997590184211731, 0.8683551549911499)

第一个是p值,越接近于1越显著

————————————————
题外话

对于CNN中的参数:

-可学习的参数:卷积层和全连接层的权重、bias、BatchNorm的 [公式] 等。

-不可学习的参数(超参数):学习率、batch_size、weight_decay、模型的深度宽度分辨率等。

6. nn.Embedding的全部参数

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)

— — — — — — — — 参数说明— — — — — — — —

(1)num_embeddings(int):语料库字典大小;

(2)embedding_dim(int):每个嵌入向量的大小;

(3)padding_idx(int, optional):输出遇到此下标时用零填充

(4)max_norm(float, optional):重新归一化词嵌入,使它们的范数小于提供的值;

(5)norm_type(float, optional):对应max_norm选项计算p范数时的p,默认值为2;

(上面的4、5两个参数基本不用,通常使用kaiming和xavier初始化参数)

(6)scale_grad_by_freq(boolean, optional):将通过小批量中单词频率的倒数来缩放梯度,默认为False。注意!这里的词频指的是自动获取当前小批量中的词频,而非整个词典;

(7) sparse(bool, optional):如果为True,则与权重矩阵相关的梯度转变为稀疏张量。

稀疏张量指反向传播时只更新当前使用词的权重矩阵,以加快更新速度。但是,即使设置 sparse=True ,权重矩阵也未必稀疏更新,原因如下:

与优化器相关,使用SGD、Adam等优化器时包含momentum项,导致不相关词的Embedding依然会叠加动量,无法稀疏更新;

使用weight_decay,即正则项计入损失值。

基本上通常需要设置的参数是前三个

7. nn.Embedding的可学习性

以下参考Pytorch nn.Embedding的基本使用_nn.embedding使用_iioSnail的博客-CSDN博客

————————训练代码————————
import torch

import torch.nn as nn

num_embeddings= 1000 #词典长度

embedding_dim= 5

embed = nn.Embedding(num_embeddings,embedding_dim)

optimizer = torch.optim.SGD(embed.parameters(), lr=0.1)

criteria = nn.MSELoss()

for i in range(1000):

    outputs = embed(torch.LongTensor([0,1,2,3,4]))

    loss = criteria(outputs, torch.ones(5, 5))

    loss.backward()

    optimizer.step()

    optimizer.zero_grad()

————————训练结果————————

在上面例子中,我们对nn.Embedding不断的计算损失和梯度下降,让其编码往1的方向靠近(torch.ones),而且前向传播总是编码同一个[0,1,2,3,4]

训练结束后,我们再次尝试使用embedding进行编码:

执行embed(torch.LongTensor([0,1,2,3,4])),得到: 

tensor([[0.9996, 0.9999, 0.9999, 0.9994, 0.9996],

        [1.0001, 0.9995, 0.9996, 0.9998, 0.9992],

        [0.9998, 0.9994, 1.0006, 0.9999, 0.9995],

        [0.9993, 0.9998, 0.9997, 0.9998, 0.9995],

        [0.9998, 0.9990, 1.0000, 0.9994, 1.0005]],

      grad_fn=<EmbeddingBackward0>)

可以看到,经过训练后,embedding的参数发生了变化,把它们都编码成了非常接近1。

————————训练之前————————

但是初始化的时候是这样的,和1没有那么接近:

最开始的时候,执行embed(torch.LongTensor([0,1,2,3,4]))是这样的:

tensor([[ 0.1397, 0.1655, -0.3371, 0.0109, -0.1257],

        [-1.0671,  1.1212,  0.4947,  0.5827, -0.7198],

        [-0.8692, -0.8575,  0.2471,  0.5753,  1.9026],

        [-1.5764, -0.2137, -0.8645, -0.3380, -0.9576],

        [-0.0838,  0.6767, -0.6519,  1.3508,  0.6306]],

      grad_fn=<EmbeddingBackward0>)

相关文章

  • nn.Embedding

    官网地址:Embedding — PyTorch master documentation[https://pyt...

  • 2023-08-24

    马上就要考试了,还是如往常那般的没有底气。其实在最开始的时候,我还是很期待自己的,但是这么多次考下来,我开始逐渐的...

  • 2023-08-24

    1. 山不解释自己的高度,并不影响它的耸立云端。 海不解释自己的深度,并不影响它容纳百川。 地不解释自己的厚度,但...

  • pytorch0.4.1报错Padding_idx must b

    pytorch0.3.1时这样设置embedding,没有问题但0.4.1版本nn.embedding函数有改变,...

  • Pytorch中nn.Embedding模块

    https://zhuanlan.zhihu.com/p/341176854[https://zhuanlan.z...

  • pytorch之词嵌入

    nn.Embedding()函数. 在做词嵌入之前,首先要将每个词用一个数字表示,这个数字是单词在词库中的序号。 ...

  • 2023-08-24 不必太在意。

    不必太在意。 如何对待生活中的那些琐碎的事情,也许并不需要我们去太过于认真,用一个词语来形容这个对生活的视角或者是...

  • 通俗讲解pytorch中nn.Embedding原理及使用

    函数调用形式 其为一个简单的存储固定大小的词典的嵌入向量的查找表,意思就是说,给一个编号,嵌入层就能返回这个编号对...

  • 极简随笔之初为人父

    时间:2020,0202,02:02:02 我儿子出生了...... !?......???!!!。

  • 本特利探头 330105-02-12-10-02-00

    本特利BENTLY反装探头 330105-02-12-05-02-05 330105-02-12-05-02-05...

网友评论

      本文标题:2023-08-24 02 nn.Embedding

      本文链接:https://www.haomeiwen.com/subject/ofvpmdtx.html