第N2周:Embeddingbag与Embedding详解

        词嵌入是一种用于自然语言处理 (NLP) 的技术,用于将单词表示为数字,以便计算机可以处理它们。通俗的讲就是,一种把文本转为数值输入到计算机中的方法。

        Embedding和EmbeddingBag则是PyTorch中的用来处理文本数据中词嵌入(word embedding)的工具,它们将离散的词汇映射到低维的连续向量空间中,使得词汇之间的语义关系能够在向量空间中得到体现。

1. Embedding详解

        Embedding是PyTorch中最基本的词嵌入操作,TensorFlow中也有相同的函数,功能是一样。它将每个离散的词汇映射到一个低维的连续向量空间中,并且保持了词汇之间的语义关系。在PyTorch中,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, _freeze=False, device=None,

                                dtype=None)

官方API地址:Embedding — PyTorch 2.3 documentation

常用参数:

num_embeddings: #词汇表大小,最大整数index + 1
embedding_dim:  #词向量的维度

简单示例,用Embedding将两个句子转换为词嵌入向量:

import torch
import torch.nn as nn

vocab_size = 12 #词汇表大小
embedding_dim  = 4 #嵌入向量的维度

#创建一个embedding层
embedding = nn.Embedding(vocab_size, embedding_dim)

#假设我们有一个包含两个单词索引的输入序列
input_sequence1 = torch.tensor([1,5,8], dtype = torch.long)
input_sequence2 = torch.tensor([2,4], dtype = torch.long)

#使用Embedding层将输入序列转换为词嵌入
embedded_sequence1 = embedding(input_sequence1)
embedded_sequence2 = embedding(input_sequence2)

print(embedded_sequence1)
print(embedded_sequence2)

        上例中,我们定义了简单的词嵌入模型

        将大小为12的词汇表中的每个词映射到了一个4维的向量空间中。输入了两个句子,分别是[1, 5, 8]和[2, 4],每个数字代表着词汇表中的一个词汇的索引。将这两个句子通过Embedding转换为词嵌入向量,并输出结果。结果中,每个句子中的每个词汇都被映射成了4维的向量。

2. EmbeddingBag详解

        EmbeddingBag是在Embedding基础上进一步优化的工具。主要优化点在于:它可以直接处理不定长的句子,并可计算句子中所有词汇的词嵌入向量的均值或总和。前者可以简化使用,后者则可即时评估向量生成效果。
        在Pytorch中,EmbeddingBag的输入是一个整数张量和一个偏移量张量,每个整数都代表着一个词汇的索引,偏移量则表示句子中每个词汇的位置,输出是一个浮点型的张量。每个浮点数都代表这对应句子的词嵌入向量的均值或总和。

        示例:用EmbeddingBag将两个句子转换为词嵌入向量并计算它们的均值。

import torch
import torch.nn as nn

vocab_size = 12 #词汇表大小
embedding_dim = 4 #嵌入向量维度

#创建一个EmbeddingBag层
embedding_bag = nn.EmbeddingBag(vocab_size, embedding_dim, mode = 'mean')

#假设我们有两个不同长度的输入序列
input_sequence1 = torch.tensor([1, 5, 8], dtype = torch.long)
input_sequence2 = torch.tensor([2, 4], dtype = torch.long)

#将两个输入序列拼接在一起,并创建一个偏移张量
input_sequences = torch.cat([input_sequence1, input_sequence2])
offsets = torch.tensor([0,len(input_sequence1)], dtype = torch.long)

#使用EmbeddingBag层计算序列汇总(这里使用平均值)
embedded_bag = embedding_bag(input_sequences, offsets)

print(embedded_bag)

        在该示例中,模型构建步骤如下:

        定义一个大小为12的词汇表,并将每个词汇映射到一个4维的向量空间中。输入两个句子,分别为[1, 5, 8]和[2, 4],每个数字代表词汇表中的一个词汇的索引。通过EmbeddingBag将每个句子中的每个词汇转换为词嵌入向量,并计算它们的均值。结果表明,每个句子的词嵌入向量的均值都是一个4维的向量。

EmbeddingBag层中的mode参数用于指定如何对每个序列中的嵌入向量进行汇总。常用模式主要有3种:sum、mean、max。

        'sum':此模式计算每个序列的嵌入向量之和。当您想要捕获序列中包含的整体信息时,它非常有用。例如,假设有一个序列[2,3,1],每个数字表示一个离散特征的索引,对应的嵌入式向量分别为[0.1,0.2,0.3]、[0.2,0.3,0.4]和[0.3,0.4,0.5],则使用 'sum'模式汇总后的嵌入向量为[0.6,0.9,1.2]。

        'mean':在此模式下,计算每个序列的嵌入向量的平均值。它通常用于获取考虑序列不同长度的代表性向量。

        'max':'max' 模式计算每个序列的嵌入向量每个维度的最大值。当您想要关注序列中最重要的特征时,它非常有用。

模式选择主要取决于具体的任务和数据集。

文本分类任务中,通常使用mean模式,因为它可以捕捉到每个序列的平均嵌入,反映出序列的整体含义。

序列标注任务中,通常使用sum模式,因为它可以捕捉到每个序列的所有信息,不会丢失任何关键信息。

3. 任务描述

任务要求:
加载附件中的.txt文件,并使用EmbeddingBag和Embedding完成词嵌入。

附件内容:

比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。
为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:

1.文本处理

# ------文本处理,将句子转换为整数序列 ------
import torch
import jieba

# 确认打开的文本文件路径和文件名
file_name = "E:\谷歌下载\任务文件.txt"

# 从文件中读取文本行,并替代预定义的Sentences
with open(file_name, "r", encoding = "utf-8") as file:
    Context     = file.read()
    Sentences   = Context.split()
    print("==== 文本分句: ====\n", Sentences)     # 打印核对结果

# 使用jieba.cut()函数逐句进行分词,结果输出为一个列表
tokenized_texts = [list(jieba.lcut(sentence)) for sentence in Sentences]
print("==== 分词结果: ====\n", tokenized_texts)   # 打印核对结果

# 构建词汇表
word_index = {}
index_word = {}
for i, word in enumerate(set([word for text in tokenized_texts for word in text])):
    word_index[word] = i
    index_word[i]    = word

print("==== 词汇表: ====\n", word_index)          # 打印核对结果

# 将文本转化为整数序列
sequences = [[word_index[word] for word in text] for text in tokenized_texts]
print("==== 文本序列: ====\n",sequences)          # 打印核对结果

# 获取词汇表大小, 并+1
vocab_size      = len(word_index) + 1

2.Embedding

# 创建一个Embedding层
embedding_dim   = 100               # 定义嵌入向量的维度
embedding   = torch.nn.EmbeddingBag(vocab_size, embedding_dim, mode = "mean")
# 将多个输入序列拼接在一起,并创建一个偏移量张量
# 首先需要创建空张量和空列表
input   = torch.tensor([], dtype = torch.long)
offset  = []
# 逐句处理,进行张量拼接、向列表中添加偏移量数值
for sequence in sequences:
    offset.append(len(input))
    input   = torch.cat([input, torch.tensor(sequence, dtype= torch.long)])

# 将列表形式的偏移量转换为张量形式,用于embedding_bag()函数的输入
offset = torch.tensor(offset, dtype = torch.long)

# 检查序列张量拼接和索引生成结果
print("-"*80)    
print(offset)
print(input)
print("-"*80)

# 使用Embedding层将输入序列转换为词嵌入
embeddeding = embedding(input, offset)

# 打印输出结果
print("词嵌入结果: \n", embeddeding)

3.EmbeddingBag 

# 创建一个EmbeddingBag层
embedding_dim   = 100               # 定义嵌入向量的维度
embedding_bag   = torch.nn.EmbeddingBag(vocab_size, embedding_dim, mode = "mean")

# 将多个输入序列拼接在一起,并创建一个偏移量张量
# 首先需要创建空张量和空列表
input   = torch.tensor([], dtype = torch.long)
offset  = []
# 逐句处理,进行张量拼接、向列表中添加偏移量数值
for sequence in sequences:
    offset.append(len(input))
    input   = torch.cat([input, torch.tensor(sequence, dtype= torch.long)])

# 将列表形式的偏移量转换为张量形式,用于embedding_bag()函数的输入
offset = torch.tensor(offset, dtype = torch.long)

# 检查序列张量拼接和索引生成结果
print("-"*80)    
print(offset)
print(input)
print("-"*80)

# 使用Embedding层将输入序列转换为词嵌入
embedded_bag = embedding_bag(input, offset)

# 打印输出结果
print("词嵌入结果: \n", embedded_bag)

  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

房FF房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值