在使用pytorch或tensorflow等神经网络框架进行nlp任务的处理时,能够经过对应的Embedding层作词向量的处理,更多的时候,使用预训练好的词向量会带来更优的性能。下面分别介绍使用gensim和torchtext两种加载预训练词向量的方法。git
1.使用gensim加载预训练词向量
对于以下这样一段语料github
test_sentence = """When forty winters shall besiege thy brow,
And dig deep trenches in thy beauty's field,
Thy youth's proud livery so gazed on now,
Will be a totter'd weed of small worth held:
Then being asked, where all thy beauty lies,
Where all the treasure of thy lusty days;
To say, within thine own deep sunken eyes,
Were an all-eating shame, and thriftless praise.
How much more praise deserv'd thy beauty's use,
If thou couldst answer 'This fair child of mine
Shall sum my count, and make my old excuse,'
Proving his beauty by succession thine!
This were to be new made when thou art old,
And see thy blood warm when thou feel'st it cold.""".split()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
构建词表,此过程也可以使用Keras或torchtext来简化完成,完整代码见文末仓库。缓存
# 给每一个单词编码,也就是用数字来表示每一个单词,这样才可以传入word embeding获得词向量。
vocab = set(test_sentence) # 经过set将重复的单词去掉
word_to_idx = {word: i+1 for i, word in enumerate(vocab)}
# 定义了一个unknown的词,也就是说没有出如今训练集里的词,咱们都叫作unknown,词向量就定义为0。
word_to_idx['<unk>'] = 0
idx_to_word = {i+1: word for i, word in enumerate(vocab)}
idx_to_word[0] = '<unk>'
1
2
3
4
5
6
7
使用gensim加载已训练好的word2vec词向量,此处用的是glove已训练好的词向量,下载连接:https://pan.baidu.com/s/1i5XmTA9 由于glove词向量和word2vec词向量格式略有不一样,先使用gensim的scripts.glove2word2vec方法将glove词向量转化为word2vec词向量的格式。转化方式很简单,以下:网络
from gensim.test.utils import datapath, get_tmpfile
from gensim.models import KeyedVectors
# 已有的glove词向量
glove_file = datapath('test_glove.txt')
# 指定转化为word2vec格式后文件的位置
tmp_file = get_tmpfile("test_word2vec.txt")
from gensim.scripts.glove2word2vec import glove2word2vec
glove2word2vec(glove_file, tmp_file)
1
2
3
4
5
6
7
8
去词向量文件中查表,获得词表中单词对应的权重weight。在词向量文件中没匹配到的单词则继续保留全0向量。框架
# 使用gensim载入word2vec词向量
wvmodel = gensim.models.KeyedVectors.load_word2vec_format('/Users/wyw/Documents/vectors/word2vec/word2vec.6B.100d.txt', binary=False, encoding='utf-8')
vocab_size = len(vocab) + 1
embed_size = 100
weight = torch.zeros(vocab_size, embed_size)less
for i in range(len(wvmodel.index2word)):
try:
index = word_to_idx[wvmodel.index2word[i]]
except:
continue
weight[index, :] = torch.from_numpy(wvmodel.get_vector(
idx_to_word[word_to_idx[wvmodel.index2word[i]]]))
1
2
3
4
5
6
7
8
9
10
11
12
13
获得weight权重后,便可在PyTorch的Embedding层中就能够指定预训练的词向量。工具
embedding = nn.Embedding.from_pretrained(weight)
# requires_grad指定是否在训练过程当中对词向量的权重进行微调
self.embedding.weight.requires_grad = True
1
2
3
完整代码见个人github仓库:https://github.com/atnlp/torchtext-summary 下的Language-Model.ipynb文件性能
2.使用torchtext加载预训练的词向量
下面介绍如何在torchtext中使用预训练的词向量,进而传送给神经网络模型进行训练。关于torchtext更完整的用法见我另外一篇博客:TorchText用法示例及完整代码ui
使用torchtext默认支持的预训练词向量
默认状况下,会自动下载对应的预训练词向量文件到当前文件夹下的.vector_cache目录下,.vector_cache为默认的词向量文件和缓存文件的目录。编码
from torchtext.vocab import GloVe
from torchtext import data
TEXT = data.Field(sequential=True)
# 如下两种指定预训练词向量的方式等效
# TEXT.build_vocab(train, vectors="glove.6B.200d")
TEXT.build_vocab(train, vectors=GloVe(name='6B', dim=300))
# 在这种状况下,会默认下载glove.6B.zip文件,进而解压出glove.6B.50d.txt, glove.6B.100d.txt, glove.6B.200d.txt, glove.6B.300d.txt这四个文件,所以咱们能够事先将glove.6B.zip或glove.6B.200d.txt放在.vector_cache文件夹下(若不存在,则手动建立)。
1
2
3
4
5
6
7
指定预训练词向量和缓存文件所在目录
上述使用预训练词向量文件的方式存在一大问题,即咱们每作一个nlp任务时,创建词表时都须要在对应的.vector_cache文件夹中下载预训练词向量文件,如何解决这一问题?咱们可使用torchtext.vocab.Vectors中的name和cachae参数指定预训练的词向量文件和缓存文件的所在目录。所以咱们也可使用本身用word2vec等工具训练出的词向量文件,只需将词向量文件放在name指定的目录中便可。
经过name参数能够指定预训练的词向量文件所在的目录
默认状况下预训练词向量文件和缓存文件的目录位置都为当前目录下的 .vector_cache目录,虽然经过name参数指定了预训练词向量文件存在的目录,可是由于缓存文件的目录没有特殊指定,此时在当前目录下仍然须要存在 .vector_cache 目录。
# glove.6B.200d.txt为预先下载好的预训练词向量文件
if not os.path.exists(.vector_cache):
os.mkdir(.vector_cache)
vectors = Vectors(name='myvector/glove/glove.6B.200d.txt')
TEXT.build_vocab(train, vectors=vectors)
1
2
3
4
5
经过cache参数指定缓存目录
# 更进一步的,能够在指定name的同时同时指定缓存文件所在目录,而不是使用默认的.vector_cache目录
cache = '.vector_cache'
if not os.path.exists(cache):
os.mkdir(cache)
vectors = Vectors(name='myvector/glove/glove.6B.200d.txt', cache=cache)
TEXT.build_vocab(train, vectors=vectors)
1
2
3
4
5
6
在模型中指定Embedding层的权重
在使用预训练好的词向量时,咱们须要在神经网络模型的Embedding层中明确地传递嵌入矩阵的初始权重。权重包含在词汇表的vectors属性中。以Pytorch搭建的Embedding层为例:
# 经过pytorch建立的Embedding层
embedding = nn.Embedding(2000, 256)
# 指定嵌入矩阵的初始权重
weight_matrix = TEXT.vocab.vectors
embedding.weight.data.copy_(weight_matrix )
1
2
3
4
5
一个比较完整的示例
import torch
from torchtext import data
from torchtext import datasets
from torchtext.vocab import GloVe
import numpy as np
def load_data(opt):
# use torchtext to load data, no need to download dataset
print("loading {} dataset".format(opt.dataset))
# set up fields
text = data.Field(lower=True, include_lengths=True, batch_first=True, fix_length=opt.max_seq_len)
label = data.Field(sequential=False)
# make splits for data
train, test = datasets.IMDB.splits(text, label)
# build the vocabulary
text.build_vocab(train, vectors=GloVe(name='6B', dim=300))
label.build_vocab(train)
# print vocab information print('len(TEXT.vocab)', len(text.vocab)) print('TEXT.vocab.vectors.size()', text.vocab.vectors.size())1234567891011121314151617181920212223完整代码见个人GitHub仓库:https://github.com/atnlp/torchtext-summary关于torchtext的其余用法见个人博客:http://www.nlpuser.com/pytorch/2018/10/30/useTorchText/我的原创,未经容许不得转载。--------------------- 做者:nlpuser 来源:CSDN 原文:https://blog.csdn.net/nlpuser/article/details/83627709 版权声明:本文为博主原创文章,转载请附上博文连接!