2023-08-24 02 nn.Embedding

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>)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容