之前已将pytorch的tutorial看过了,但是并没有用pytorch做什么项目,一直以来都是用tensorflow搭建框架,但是因为其是静态网络,不能处理if…else等等操作,于是转而用pytorch实现,将遇到的一些问题放在此处,因为脑子不好使啊,哈哈
如果是随机初始化的向量,是这么定义的:
self.word_embeds = nn.Embedding(vocab_size, embedding_dim)
如果pretrained_weight是已经训练好的词向量,加载方式一如下:
self.word_embeds = nn.Embedding(vocab_size, embedding_dim)
pretrained_weight = np.array(pretrained_weight)
self.embed.weight.data.copy_(torch.from_numpy(pretrained_weight))
https://www.cnblogs.com/bamtercelboo/p/7469005.html
加载方式二:
self.word_embeds = nn.Embedding(vocab_size, embedding_dim)
if pre_word_embeds is not None:
self.pre_word_embeds = True
self.word_embeds.weight = nn.Parameter(torch.FloatTensor(pre_word_embeds))
else:
self.pre_word_embeds = False
详解 Pytorch自带nn.Embedding模块
self.embed = nn.Embedding(vocab_size, embedding_dim)
那么,如何使用已经训练好的词向量呢?
词向量其实是模型的embedding层的权重,所以,如下方法便可以实现:
self.embed = nn.Embedding(vocab_size, embedding_dim)
self.embed.weight.data.copy_(torch.from_numpy(pretrained_embeddings))
同时,使用已经训练好的词向量之后,我们又有如下选择,即保持词向量不更新(固定词向量),或者基于加载的词向量进行更新权重,很多人往往会忘记这一点。
不需要改变,因此就涉及到固定子层参数不更新的技巧。这个方法有很多,常用的是requires_grad和volatile,requires_grad = False等同于volatile = True。
self.embed = nn.Embedding(V, D)
self.embed.weight.data.copy_(torch.from_numpy(pretrained_embeddings))
self.embed.weight.requires_grad = False
因此我们可以设置embeding层的参数的parameter的requires_grad为False,这样就不会计算其梯度了,这样还会提升模型训练的速度,因为预训练的词向量矩阵维度很大,如果每次反向传播都计算它的梯度会极大地影响训练的速度。此外,设置优化器的时候,第一个参数就不可以是model.parameter(),因为embeding层的梯度是没有的,也就优化不了,因此要将它排除。代码如下:
optimizer = torch.optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr=lr, weight_decay=opt.weight_decay)
代码使用了过滤器将requires_grad为False的过滤掉(默认为True),这样就可以保证代码的正确性。
如何在pytorch中使用word2vec训练好的词向量
torch.nn.Embedding()
这个方法是在pytorch中将词向量和词对应起来的一个方法. 一般情况下,如果我们直接使用下面的这种:
self.embedding = torch.nn.Embedding(num_embeddings=vocab_size, embedding_dim=embeding_dim)
num_embeddings=vocab_size 表示词汇量的大小
embedding_dim=embeding_dim 表示词向量的维度
这种情况下, 因为没有指定训练好的词向量, 所以embedding会帮咱们生成一个随机的词向量(但是在我刚刚测试的一个情感二分类问题中, 我发现好像用不用预训练的词向量, 结果差不多, 不过不排除是因为当时使用的模型比较简单, 导致一些特征根本就没提取出来).
如果我想使用word2vec预训练好的词向量该怎么做呢?
其实很简单,pytorch已经给我们提供好了接口
self.embedding.weight.data.copy_(torch.from_numpy(embeding_vector))
self.embedding.weight.requires_grad = False
上面两句代码的意思, 第一句就是导入词向量, 第二句表示的是在反向传播的时候, 不要对这些词向量进行求导更新. 我还看到有人会在优化器那里使用这样的代码:
# emotion_net是我定义的模型
optimizer = torch.optim.Adam(filter(lambda p: p.requires_grad, emotion_net.parameters()), lr=1e-3, betas=(0.9, 0.99))
大概意思也是为了保证词向量不会被反向传播而更新, 具体有没有用我就不清楚了.
其实我感觉大家比较在意的其实应该是embeding_vector的形式, 下面我就介绍一下embeding_vector的形式
为了讲述方便, 这里定义出下面几个矩阵
1.embeding_vector:表示词向量,每行是一个词的词向量,有多少行就说明有多少单词;
2.word_list:表示单词列表,里面就是单词;
3.word_to_index:这个矩阵将word_list中的单词和embeding_vector中的位置对应起来.
![](https://img.haomeiwen.com/i4070307/8be8b7f0a35bd656.png)
网友评论