NN.Embedding是PyTorch中的一个常用模块,其主要作用是将输入的整数序列转换为密集向量表示。在自然语言处理(NLP)任务中,可以将每个单词表示成一个向量,从而方便进行下一步的计算和处理。
一、创建一个Embedding层
我们可以使用下面的代码创建一个Embedding层:
import torch.nn as nn
# 定义一个 Embedding 层,输入大小为 10,输出大小为 3
embedding = nn.Embedding(10, 3)
这里定义了一个输入大小为10,输出大小为3的Embedding层。其中输入大小10表示一共有10个单词或者是10个离散的特征,输出大小3表示每个单词/特征会被嵌入到一个3维的向量中。
二、查看Embedding层的参数
我们可以通过打印出Embedding层的参数来更好地理解它的作用:
print(embedding.weight)
输出结果如下:
tensor([[-0.4555, 2.0056, 0.3216],
[-0.8817, -0.8111, 1.1015],
[-1.0718, 0.6407, -0.2452],
[-0.1458, -0.4591, 0.3504],
[ 0.0302, 0.5518, -0.8721],
[-0.1264, -1.5344, 0.6339],
[-0.6904, -1.8824, -0.2472],
[ 0.5966, -0.9738, 0.9559],
[ 0.0134, -1.3174, -0.3511],
[ 1.1453, 2.5714, 0.1814]], requires_grad=True)
从上面的输出结果中,我们可以看到一个大小为10x3的矩阵。其中的每一行代表了一个单词/特征的嵌入向量,每个元素都是一个浮点数。这个矩阵的值是在模型训练的过程中学习得到的。
三、输入数据并获取嵌入向量
我们可以使用下面的代码输入一个整数序列并获取嵌入向量:
# 输入一个大小为3的整数序列
input_sequence = torch.LongTensor([1, 5, 3])
# 获取嵌入向量
embedded_sequence = embedding(input_sequence)
print(embedded_sequence)
输出结果如下:
tensor([[-0.8817, -0.8111, 1.1015],
[-0.1264, -1.5344, 0.6339],
[-0.1458, -0.4591, 0.3504]], grad_fn=<EmbeddingBackward>)
从上面的输出结果中,我们可以看到一个大小为3x3的矩阵。其中的每一行代表了输入整数序列中对应的单词/特征嵌入向量,可以看到这个结果是和上面我们看到的参数是相一致的。
四、嵌入层在情感分析中的应用举例
举个例子,我们可以使用NN.Embedding来进行情感分析。下面的代码演示了如何将一段文本中的单词转换成嵌入向量,并使用卷积神经网络(CNN)进行情感分类:
import torch
import torch.nn as nn
import torch.nn.functional as F
class SentimentClassifier(nn.Module):
def __init__(self, vocab_size, embedding_dim, num_filters, filter_sizes, output_dim, pretrained_embeddings):
super().__init__()
# 定义 Embedding 层
self.embedding = nn.Embedding(vocab_size, embedding_dim)
# 定义卷积层
self.convs = nn.ModuleList([
nn.Conv2d(in_channels=1, out_channels=num_filters, kernel_size=(fs, embedding_dim))
for fs in filter_sizes
])
# 定义全连接层
self.fc = nn.Linear(len(filter_sizes) * num_filters, output_dim)
# 加载预训练的嵌入层权重
self.embedding.weight.data.copy_(pretrained_embeddings)
def forward(self, text):
# text: [batch_size, sent_len]
# 获取文本中每个单词对应的嵌入向量
embedded = self.embedding(text) # embedded: [batch_size, sent_len, emb_dim]
# 调整张量的维度使其适合卷积层的输入
embedded = embedded.unsqueeze(1) # embedded: [batch_size, 1, sent_len, emb_dim]
# 运行卷积和池化层
conved = [F.relu(conv(embedded)).squeeze(3) for conv in self.convs] # conved: [batch_size, num_filters, sent_len - filter_sizes[n] + 1]
# 对每个卷积层的输出进行最大池化
pooled = [F.max_pool1d(conv, conv.shape[2]).squeeze(2) for conv in conved] # pooled: [batch_size, num_filters]
# 把所有的池化层结果拼接到一起,作为全连接层的输入
cat = self.fc(torch.cat(pooled, dim=1))
return cat
上面的代码中,我们首先定义了一个SentimentClassifier类,该类继承自nn.Module,实现了一个简单的CNN分类器。其中,我们定义了一个Embedding层,它的参数包括词汇表的大小、嵌入维度以及一个预先训练好的嵌入向量。在前向传递过程中,我们使用了CNN对输入的单词进行特征提取,并经过一个全连接层输出情感分类的结果。
五、小结
NN.Embedding在自然语言处理任务中是一个非常常用的模块,它能够将离散的输入特征转换成密集的向量表示,并被广泛应用于文本分类、句向量生成、对话生成等任务中。