- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
Embedding(词嵌入)是一种用于自然语言处理的技术,用于将单词表示为数字,以便于计算机可以处理他们。通俗的讲就是,一种把文本转换为数值输入到计算机中的方法。
上周将文本转换为字典序列、one-hot编码,就是最早期的词嵌入方法
Embedding
和EmbeddingBag
是pytorch中用来处理文本数据中词嵌入(word embedding)的工具,它们将离散的词汇映射到低维的连续向量空间中,使得词汇之间的语义关系能够在向量空间中得到体现。
Embedding
Embedding
是pytorch中最基本的词嵌入操作,tensorflow中也有相同的函数,功能是一样的。将每个离散的词汇映射到一个低维的连续向量空间中,并且保持了词汇之间的语义关系。在pytorch中,Embeeding
的输入是一个整数张量,每个整数都代表着一个词汇的索引,输出是一个浮点型的张量,它代表着对应词汇的词嵌入向量。
嵌入层使用随机权重初始化,并将学习数据集中所有词的嵌入,它是一个灵活的层,可以以各种方式使用。如:
- 可以用作深度学习模型的一部分,其中嵌入与模型本身一起被学习
- 可以用于加载训练好的词嵌入模型
嵌入层往往被定义为网络的第一个隐藏层。
函数原型
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)
num_embeddings
词汇表的大小,最大整数index + 1embedding_dim
词向量的维度
示例
import torch
import torch.nn as nn
vocab_szie = 12
embedding_dim = 4
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维的向量空间中。
EmbeddingBag
EmbeddingBag
是在Embedding
的基础上进一步优化的工具,它可以直接处理不定长的句子,并且可以计算句子中所有词汇的词嵌入向量的均值或总和。在pytorch中,EmbeddingBag的输入是一个整数张量和一个偏移量张量,每个整数都代表着一个词汇的索引,偏移量则表示句子中每个词汇的位置,输出是一个浮点型的张量,每个浮点数都代表着对应句子的词嵌入向量的均值或总和。
示例
import torch
import torch.nn as nn
vocab_size =12
embedding_dim = 4
embedding_bag = nn.EmbeddingBag(vocab_size, embedding_dim, mode='mean')
# 造2个假的输入序列
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)
embedding_bag = embedding_bag(input_sequences, offsets)
print(embedding_bag)
在上面的例子中,我们定义将大小为12的词汇表映射到4维向量的嵌入层,然后输入了两个句子,返回的结果形状为2,4
,正好对应于句子的个数和向量的维度。
EmbeddingBag
层中的mode
参数用于指定如何对每个序列中的嵌入向量进行汇总,常用的模式有三种:sum
、mean
和max
sum
将每个序列中的嵌入向量相加mean
将每个序列中的嵌入向量求平均值max
将每个序列中的嵌入向量取最大值
mode的选取通常取决于具体的任务和数据集,例如:在文本分类任务中,通常使用mean
模式,因为它可以捕捉到每个序列的平均嵌入,反映出序列的整体含义;而在序列标记任务中,通常使用sum
模式,因为它可以捕捉到每个序列的所有信息,不会丢失任何关键信息。在实际应用中,可以根据具体的情况灵活选择汇总模式,以获得最佳效果。
任务
import jieba
# 文本处理
content = open('task.txt', 'r').read()
lines = content.strip().split('\n')
word_index = {}
index_word = {}
idx = 0
# 制作并获取字典序号
def get(word):
global idx
if word not in word_index:
word_index[word] = idx
index_word[idx] = word
idx += 1
return word_index[word]
vectors = []
for line in lines:
vec = []
for word in jieba.cut(line):
i = get(word)
vec.append(i)
vectors.append(vec)
print('vocab_size:', len(word_index))
print('vector:', vectors)
使用Embedding完成词嵌入
embedding = nn.Embedding(len(word_index), 32)
for vec in vectors:
inputs = torch.tensor(vec, dtype=torch.long)
output = embedding(inputs)
print(output)
使用EmbeddingBag完成词嵌入
embedding_bag = nn.EmbeddingBag(len(word_index), 32, mode='mean')
offsets = torch.tensor([0, len(vectors[0])], dtype=torch.long)
inputs = torch.cat([torch.tensor(vec, dtype=torch.long) for vec in vectors])
outputs = embedding_bag(inputs, offsets)
print(outputs)
总结与心得体会
在没有进行代码实践以前,我一直以为词嵌入是基于输入的,不论是句子还是词汇,输出的都是固定维度的向量。也就是EmbeddingBag,而真正的Embedding是只针对词来做处理的。
还有一个值得注意的点是,EmbeddingBag层计算时要求输入的offsets其实是每个句子的起始索引。这里面包含了两个知识点,一个是,我们使用torch.cat实际将两个句子无缝合并成了一个向量。然后使用offsets来提供每个句子的起始索引。因此登假设offsets中有N个索引,最终的输出结果就是(N,32)维度的向量。