nn.Embedding 学习笔记

75 篇文章 2 订阅

1. nn.Embedding

1.1 说明

torch.nn.Embedding官网链接

  • 作用:一个简单的查找表,存储固定字典和大小的嵌入。这个模块通常用于存储单词嵌入并使用索引检索它们。模块的输入是一个索引列表,输出是相应的单词嵌入。
  • 函数:embeddings = nn.Embedding(10, 3,padding_idx=2):表示创建一个行数为10,列数为3的表,其中第2行全部填充为0。
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, device=None, dtype=None)
  • num_embeddings:嵌入字典的大小;即一个字典中有多少个词
  • embedding_dim:每个嵌入词的大小
  • padding_idx:如果指定了,padding_idx上的条目不会对渐变做出贡献;因此,在padding_idx处的嵌入向量在训练过程中没有更新,即保持为一个固定的“pad”。对于一个新构造的Embedding,在padding_idx的嵌入向量将默认为全部为零,但是可以更新为另一个值来用作填充向量。
  • max_norm:如果给定,每个范数大于max_norm的嵌入向量被重新规范化为具有范数max_norm
  • norm_type:默认为2.0;为max_norm选项计算的p-norm的p
  • scale_grad_by_freq:默认False 如果给定,这将按小批量中单词频率的倒数来缩放梯度
  • sparse:默认False ,如果为真,梯度w。r。t。权矩阵将是一个稀疏张量。有关稀疏梯度的更多细节,请参见注释。
  • embedding_weight:可学习权值模块,形状为:(num_embeddings,embedding_dim),其值采样来自于 N ∼ ( 0 , 1 ) N\sim(0,1) N(0,1)

1.2 代码-随机生成表

  • 代码:
# -*- coding: utf-8 -*-
# @Project: zc
# @Author: zc
# @File name: embedding_test
# @Create time: 2022/2/9 22:13

import torch
from torch import nn

embeddings = nn.Embedding(10, 3,padding_idx=2)
input = torch.LongTensor([[1, 2, 4, 5], [4, 3, 2, 9]])
# padding_idx=2;表示将第2行填充为0;
# input的意思是我们从创建的表格中拿去指定的行出来
# [1,2,4,5] 代表拿出来 第1行,第2行,第4行,第5行
# [4,3,2,9] 代表拿出来 第4行,第3行,第2行,第9行
output = embeddings(input)

print(f"embeddings.weight={embeddings.weight}")
print(f"input={input}")
print(f"output={output}")
  • 结果:
embeddings.weight=Parameter containing:
tensor([[ 0.6994, -0.1277, -0.5135],
        [ 0.4721, -0.7914,  0.2188],
        [ 0.0000,  0.0000,  0.0000],
        [ 0.5628,  0.6102, -0.0117],
        [-1.0229, -1.4277, -1.2109],
        [-0.6633,  0.1509, -0.8726],
        [ 0.2847, -0.0359, -0.4973],
        [ 0.5888,  0.9830,  0.9432],
        [ 0.1455,  0.3187,  0.9861],
        [-1.4602,  1.1570,  0.1492]], requires_grad=True)
input=tensor([[1, 2, 4, 5],
        [4, 3, 2, 9]])
output=tensor([[[ 0.4721, -0.7914,  0.2188],
         [ 0.0000,  0.0000,  0.0000],
         [-1.0229, -1.4277, -1.2109],
         [-0.6633,  0.1509, -0.8726]],

        [[-1.0229, -1.4277, -1.2109],
         [ 0.5628,  0.6102, -0.0117],
         [ 0.0000,  0.0000,  0.0000],
         [-1.4602,  1.1570,  0.1492]]], grad_fn=<EmbeddingBackward>)

1.3 代码-自定义表

# -*- coding: utf-8 -*-
# @Project: zc
# @Author: zc
# @File name: embedding_test_new
# @Create time: 2022/4/25 15:29

import torch
from torch import nn

# 自定义一个3行4列的矩阵
my_source = torch.arange(12, dtype=torch.float32).reshape((3, 4))
# my_source=tensor([[ 0.,  1.,  2.,  3.],  第 0 行
#                   [ 4.,  5.,  6.,  7.],  第 1 行
#                   [ 8.,  9., 10., 11.]]) 第 2 行
# 将自定义的表格作为nn.Embedding处理
my_table = nn.Embedding.from_pretrained(my_source)

# input为查询索引表
input = torch.Tensor([[1,2],[0,2]]).to(torch.int32)
# [[1,2],[0,2]]表示从3行4列表格中分别拿到如下行
# [1,2]: 第1行[4,5,6,7],第2行[8,9,10,11]
# [0,2]: 第0行[0,1,2,3],第2行[8,9,10,11]
# 根据input的索引表去索引自定义表格
output = my_table(input)
# 所以output输出如下:

# output=tensor([[[ 4.,  5.,  6.,  7.],
#                 [ 8.,  9., 10., 11.]],
# 
#                [[ 0.,  1.,  2.,  3.],
#                 [ 8.,  9., 10., 11.]]])

# 打印自定义表格
print(f"my_source={my_source}")

print(f"my_table={my_table}")
print(f"output={output}")

2. nn.EmbeddingBag

nn.Embedding嵌入式词袋,就是在原来的nn.Embedding的基础上加上一个mode ;注意,在这里我代码测试是选出的行组成的词表后求和用的是torch.sum(dim=0) 。很奇怪是不是官网错了,以下为我的代码测试结果
在这里插入图片描述

2.1 代码

import torch
from torch import nn


# an EmbeddingBag module containing 10 tensors of size 3
# 创建一个词袋,这个词袋组成如下:
# 1. 先创建一个大小为10行3列的词矩阵
# 2. 词袋的方式为求和,即 先用输入的索引矩阵求得一个输出得到output
# 3. output_bag = torch.sum(output,dim=0)

# 实例化一个EmbeddingBag
embedding_sum = nn.EmbeddingBag(10, 3, mode='sum')

# 为了验证思路正确性,得到embedding_sum的权重weight
embedding_bag_weight = embedding_sum.weight

# 打印权重矩阵 embedding_bag_weight
print(f"embedding_bag_weight={embedding_bag_weight}")
# embedding_bag_weight=Parameter containing:
# tensor([[ 1.2337, -1.1877,  1.6401],  第 0 行
#         [-0.7979, -1.3023, -1.6140],  第 1 行
#         [ 0.1214, -1.3181,  0.2492],  第 2 行
#         [-0.2009, -1.7084, -1.6683],  第 3 行
#         [-1.2780,  0.6330, -0.9713],  第 4 行
#         [ 0.0917, -0.8060,  1.1740],  第 5 行
#         [-0.1560, -0.9084,  2.6637],  第 6 行
#         [-0.1871,  0.9832,  0.1025],  第 7 行
#         [ 0.9361,  1.2824, -1.1812],  第 8 行
#         [-0.7051,  0.3102,  0.4746]], 第 9 行         requires_grad=True)
# a batch of 2 samples of 4 indices each

# input 表示要获取词表中的第 [1,2,4,5,4,3,2,9] 行
# 得到 output_table如下:
# [-0.7979, -1.3023, -1.6140],  第 1 行   0
# [ 0.1214, -1.3181,  0.2492],  第 2 行   1
# [-1.2780,  0.6330, -0.9713],  第 4 行   2
# [ 0.0917, -0.8060,  1.1740],  第 5 行   3
# [-1.2780,  0.6330, -0.9713],  第 4 行   4
# [-0.2009, -1.7084, -1.6683],  第 3 行   5
# [ 0.1214, -1.3181,  0.2492],  第 2 行   6
# [-0.7051,  0.3102,  0.4746]], 第 9 行   7
input = torch.tensor([1,2,4,5,4,3,2,9], dtype=torch.long)

# offsets表示需要将 output_table 进行切割求和
# 第一份为 output_bag[0] = torch.sum(output_table[:4],dim=0) ;
# 第二份为 output_bag[1] = torch.sum(output_table[4:],dim=0) ;
offsets = torch.tensor([0,4], dtype=torch.long)
output_bag = embedding_sum(input, offsets)
print(f"embedding_sum(input, offsets)={output_bag}")


# 为了验证我们的想法,我们需要创建一个词表,词表的权重为embedding_bag_weight
my_embedding1 = nn.Embedding.from_pretrained(embedding_bag_weight)

# 根据同样的输入得到索引后的词表my_output1
my_output1 = my_embedding1(input)

print(f"my_output1={my_output1}")

# 将my_output1[:4] 前 4 行 按照dim=0求和,即行与行之间求和,得到sum0
sum0 = torch.sum(my_output1[:4],dim=0)
print(f"sum0={sum0}")

# 将my_output1[4:] 后 4 行 按照dim=0求和,即行与行之间求和,得到sum1
sum1 = torch.sum(my_output1[4:],dim=0)
print(f"sum1={sum1}")

# 将sum0,sum1按照行堆叠起来
cus_sum = torch.cat([sum0.unsqueeze(0),sum1.unsqueeze(0)],dim=0)
print(f"cus_sum={cus_sum}")

# 为了验证思路是否正确,将通过nn.EmbeddingBag 求得的结果output_bag
# 自定义求得的结果cus_sum 进行对比,如果为true,表示思路正确
flag = torch.isclose(output_bag, cus_sum)

print(f"flag={flag}")
# flag=tensor([[True, True, True],
#         [True, True, True]])

3. 小结

  • nn.Embedding:

nn.Embedding 步骤如下:

  1. 创建一个m行n列的矩阵词表table
  2. 根据输入的索引来按行从词表table中求得相关行得到output
  • nn.EmbeddingBag:
  1. 创建一个m行n列的矩阵词表table
  2. 根据输入的索引来按行从词表table中求得相关行得到output
  3. 将output 按照 进行分类得到批次batch,如果mode=‘sum’ 表示我们按照torch.sum(batch[0],dim=0)
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值