PyTorch在NLP任务中使用预训练词向量
在使用pytorch或tensorflow等神經(jīng)網(wǎng)絡(luò)框架進(jìn)行nlp任務(wù)的處理時(shí),可以通過對(duì)應(yīng)的Embedding層做詞向量的處理,更多的時(shí)候,使用預(yù)訓(xùn)練好的詞向量會(huì)帶來更優(yōu)的性能。下面分別介紹使用gensim和torchtext兩種加載預(yù)訓(xùn)練詞向量的方法。
1.使用gensim加載預(yù)訓(xùn)練詞向量
????對(duì)于如下這樣一段語(yǔ)料
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
????構(gòu)建詞表,此過程也可使用Keras或torchtext來簡(jiǎn)化完成,完整代碼見文末倉(cāng)庫(kù)。
# 給每個(gè)單詞編碼,也就是用數(shù)字來表示每個(gè)單詞,這樣才能夠傳入word embeding得到詞向量。
vocab = set(test_sentence) # 通過set將重復(fù)的單詞去掉
word_to_idx = {word: i+1 for i, word in enumerate(vocab)}
# 定義了一個(gè)unknown的詞,也就是說沒有出現(xiàn)在訓(xùn)練集里的詞,我們都叫做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加載已訓(xùn)練好的word2vec詞向量,此處用的是glove已訓(xùn)練好的詞向量,下載鏈接:https://pan.baidu.com/s/1i5XmTA9 因?yàn)間love詞向量和word2vec詞向量格式略有不同,先使用gensim的scripts.glove2word2vec方法將glove詞向量轉(zhuǎn)化為word2vec詞向量的格式。轉(zhuǎn)化方式很簡(jiǎn)單,如下:
from gensim.test.utils import datapath, get_tmpfile
from gensim.models import KeyedVectors
# 已有的glove詞向量
glove_file = datapath('test_glove.txt')
# 指定轉(zhuǎn)化為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
????去詞向量文件中查表,得到詞表中單詞對(duì)應(yīng)的權(quán)重weight。在詞向量文件中沒匹配到的單詞則繼續(xù)保留全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)
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權(quán)重后,即可在PyTorch的Embedding層中就可以指定預(yù)訓(xùn)練的詞向量。
embedding = nn.Embedding.from_pretrained(weight)
# requires_grad指定是否在訓(xùn)練過程中對(duì)詞向量的權(quán)重進(jìn)行微調(diào)
self.embedding.weight.requires_grad = True
1
2
3
????完整代碼見我的github倉(cāng)庫(kù):https://github.com/atnlp/torchtext-summary 下的Language-Model.ipynb文件
2.使用torchtext加載預(yù)訓(xùn)練的詞向量
下面介紹如何在torchtext中使用預(yù)訓(xùn)練的詞向量,進(jìn)而傳送給神經(jīng)網(wǎng)絡(luò)模型進(jìn)行訓(xùn)練。關(guān)于torchtext更完整的用法見我另一篇博客:TorchText用法示例及完整代碼
使用torchtext默認(rèn)支持的預(yù)訓(xùn)練詞向量
????默認(rèn)情況下,會(huì)自動(dòng)下載對(duì)應(yīng)的預(yù)訓(xùn)練詞向量文件到當(dāng)前文件夾下的.vector_cache目錄下,.vector_cache為默認(rèn)的詞向量文件和緩存文件的目錄。
from torchtext.vocab import GloVe
from torchtext import data
TEXT = data.Field(sequential=True)
# 以下兩種指定預(yù)訓(xùn)練詞向量的方式等效
# TEXT.build_vocab(train, vectors="glove.6B.200d")
TEXT.build_vocab(train, vectors=GloVe(name='6B', dim=300))
# 在這種情況下,會(huì)默認(rèn)下載glove.6B.zip文件,進(jìn)而解壓出glove.6B.50d.txt, glove.6B.100d.txt, glove.6B.200d.txt, glove.6B.300d.txt這四個(gè)文件,因此我們可以事先將glove.6B.zip或glove.6B.200d.txt放在.vector_cache文件夾下(若不存在,則手動(dòng)創(chuàng)建)。
1
2
3
4
5
6
7
指定預(yù)訓(xùn)練詞向量和緩存文件所在目錄
????上述使用預(yù)訓(xùn)練詞向量文件的方式存在一大問題,即我們每做一個(gè)nlp任務(wù)時(shí),建立詞表時(shí)都需要在對(duì)應(yīng)的.vector_cache文件夾中下載預(yù)訓(xùn)練詞向量文件,如何解決這一問題?我們可以使用torchtext.vocab.Vectors中的name和cachae參數(shù)指定預(yù)訓(xùn)練的詞向量文件和緩存文件的所在目錄。因此我們也可以使用自己用word2vec等工具訓(xùn)練出的詞向量文件,只需將詞向量文件放在name指定的目錄中即可。
通過name參數(shù)可以指定預(yù)訓(xùn)練的詞向量文件所在的目錄
????默認(rèn)情況下預(yù)訓(xùn)練詞向量文件和緩存文件的目錄位置都為當(dāng)前目錄下的 .vector_cache目錄,雖然通過name參數(shù)指定了預(yù)訓(xùn)練詞向量文件存在的目錄,但是因?yàn)榫彺嫖募哪夸洓]有特殊指定,此時(shí)在當(dāng)前目錄下仍然需要存在 .vector_cache 目錄。
# glove.6B.200d.txt為預(yù)先下載好的預(yù)訓(xùn)練詞向量文件
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參數(shù)指定緩存目錄
# 更進(jìn)一步的,可以在指定name的同時(shí)同時(shí)指定緩存文件所在目錄,而不是使用默認(rèn)的.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層的權(quán)重
在使用預(yù)訓(xùn)練好的詞向量時(shí),我們需要在神經(jīng)網(wǎng)絡(luò)模型的Embedding層中明確地傳遞嵌入矩陣的初始權(quán)重。權(quán)重包含在詞匯表的vectors屬性中。以Pytorch搭建的Embedding層為例:
# 通過pytorch創(chuàng)建的Embedding層
embedding = nn.Embedding(2000, 256)
# 指定嵌入矩陣的初始權(quán)重
weight_matrix = TEXT.vocab.vectors
embedding.weight.data.copy_(weight_matrix )
1
2
3
4
5
一個(gè)比較完整的示例
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())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
完整代碼見我的GitHub倉(cāng)庫(kù):https://github.com/atnlp/torchtext-summary
關(guān)于torchtext的其他用法見我的博客:http://www.nlpuser.com/pytorch/2018/10/30/useTorchText/
個(gè)人原創(chuàng),未經(jīng)允許不得轉(zhuǎn)載。
---------------------
作者:nlpuser
來源:CSDN
原文:https://blog.csdn.net/nlpuser/article/details/83627709
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!
總結(jié)
以上是生活随笔為你收集整理的PyTorch在NLP任务中使用预训练词向量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 理解GloVe模型(Global vec
- 下一篇: GloVe:另一种Word Embedd