一、安装
pip install gensim
使用上述安装方式会出现安装失败的情况,主要原因就是因为镜像节点太慢了,所以换个镜像节点就好了。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple gensim
二、使用GloVe预训练词向量
首先是GloVe预训练词向量的下载地址:
https://github.com/stanfordnlp/GloVe
里面有四种GloVe的预训练词向量,主要是训练语料不同,可以自己选择下载,记得挂VPN。
注意:GloVe的预训练词向量文件与Word2Vec的预训练词向量文件有一些小小的差距,Word2Vec 的词向量txt开头会有一个词个数以及向量维度,所以使用之前应该把GloVe词向量格式转化成Word2Vec词向量格式。
转化方法gensim库里面已经给出了相应的方法:
def glove2word2vec(glove_input_file, word2vec_output_file):
"""Convert `glove_input_file` in GloVe format to word2vec format and write it to `word2vec_output_file`.
Parameters
----------
glove_input_file : str
Path to file in GloVe format.
word2vec_output_file: str
Path to output file.
Returns
-------
(int, int)
Number of vectors (lines) of input file and its dimension.
"""
num_lines, num_dims = get_glove_info(glove_input_file)
logger.info("converting %i vectors from %s to %s", num_lines, glove_input_file, word2vec_output_file)
with utils.open(word2vec_output_file, 'wb') as fout:
fout.write("{0} {1}\n".format(num_lines, num_dims).encode('utf-8'))
with utils.open(glove_input_file, 'rb') as fin:
for line in fin:
fout.write(line)
return num_lines, num_dims
从 "glove2word2vec" 这个函数方 法就可以看到,首先传入之前用datapath 和 get_tmpfile 封装好的 glove_path 以及 需要保存的word2vec_path 在计算好所给定的GloVe词向量文件的词数量以及向量维度之后重新写入之前定义好的word2vec文件中。
完整的 Glove 词向量转化成 Word2Vec 词向量的代码:
from gensim.test.utils import datapath, get_tmpfile
from gensim.models import KeyedVectors
from gensim.scripts.glove2word2vec import glove2word2vec
GloVe_path = "./vector/glove.txt"
Word2Vec_path = "./vector/word2vec.txt"
# your glove file path
glove_path = datapath(GloVe_path)
# new word2vec file path
word2vec_path = get_tmpfile(Word2Vec_path)
# transfer GloVe to word2vec
glove2word2vec(glove_path, word2vec_path)
# loading model
vec_model = KeyedVectors.load_word2vec_format(word2vec_path)
到这里就已经完成了 GloVe 词向量到 Word2Vec 词向量的转化以及 预训练词向量的模型加载,接下来就是如何使用这个已经加载好的词向量模型来用到我们模型的输入上面。
================================================================================================
首先转化好的 word2vec 词向量文件中是一个 word 对应一个 vector 的格式,那么首先我们应该得到我们自己的语料的一个 vocab,利用这个 vocab 构建一个 word_to_index 以及 index_to_word。得到我们需要用到的 word 集合之后,我们需要定义一个weight = torch.zeros(vocab_size, dim_size) 来用于传给之后的 nn.Embedding。
最后一步就是利用你转化好的 word2vec 形式的预训练词向量文件中的词向量更新传入的weight。并不是每一个你的 vocab 中的单词都会有相应训练好的词向量,所以遍历一遍词向量模型中所有的单词,在你的vocab中的话就更新你的 weight.
具体实现如下所示:
import os
import torch
from gensim.test.utils import datapath, get_tmpfile
from gensim.models import KeyedVectors
from gensim.scripts.glove2word2vec import glove2word2vec
GloVe_path = "./vector/glove.840B.300d.txt"
Word2Vec_path = "./vector/word2vec.txt"
# transfer GloVe to word2vec
if not os.path.exists(Word2Vec_path):
glove2word2vec(GloVe_path, Word2Vec_path)
# loading vector model
vec_model = KeyedVectors.load_word2vec_format(Word2Vec_path, limit=100000)
# sentences_col denote train data sentences
sentences_col = ["xxxxxx xx xx xx xxxxxxxxxxxx xxxxx xxxx x",
"v v vvvvv vvvv vvvvvvvvv vvvvvv vvvvvv"]
vocab = set()
# using a demo to get vocab
for i in range(len(sentences_col)):
token_list = list(filter(None, sentences_col[i].split(" ")))
for token in token_list:
vocab.add(token)
# build word_to_index and index_to_word
word_to_index = {token: index + 1 for index, token in enumerate(vocab)}
word_to_index["PAD"] = 0
index_to_word = {index: token for token, index in word_to_index.items()}
# define weight to store vector embedding
weight = torch.zeros(len(vocab), 300)
# updating weight by vec_model embedding
for i in range(len(vec_model.index2word)):
if vec_model.index2word[i] not in word_to_index:
continue
index = word_to_index[vec_model.index2word[i]]
weight[index, :] = torch.from_numpy(vec_model.get_vector(vec_model.index2word[i]))
# test program is correct
print(weight[1:10, :])
注意事项:
1、由于GloVe向量文件转化成Word2Vec格式向量文件需要时间较长,转化一次之后直接判断是否存在这个文件就可以了,不要每一次都转化。
2、word2vec model 的加载时间很长,所以上面代码上加了一个limit,这个属性是表示只读取前 limit 个词向量,这样会快很多,而且确实后面的单词频率较低的话也没什么意义。
3、得到的词向量模型中,get_vocab(word) 方法是传入一个 word 返回相应的向量,用 numpy 存储,所以需要用torch.from_numpy() 转化一下。
第一个良心巨作,居然写了这么多 Q=Q,看来只有不想写实验的时候才会假装告诉自己写博客不算在玩。