NLP实战 使用gensim与自己语料训练word2vec fasttext模型词向量及使用

2021-03-08 20:35:39 浏览数 (2)

toc

1. 背景

本博客主要记录使用自己的语料库与Python gensim库训练word2vec fastext等模型获得相关词向量,以及训练好的词向量模型基本用法。

pip库准备

代码语言:txt复制
pip3 install jieba gensim lxml

2. 语料下载与处理

2.1 下载语料库

常用的一些中文语料库有:

互联网语料库(SogouT)

中文文本分类数据集THUCNews

李荣陆英文文本分类语料

谭松波中文文本分类语料

2.2 jieba分词

代码语言:txt复制
import jieba
import io
# 加载自己的自己的词库 若无可省略
jieba.load_userdict("words.txt")

with io.open('news.txt','r',encoding='utf-8') as content:
    for line in content:
        seg_list = jieba.cut(line)
        with io.open('seg.txt', 'a', encoding='utf-8') as output:
            # lower case
            output.write(' '.join(seg_list.lower()))

2.3 字符替换处理

如使用sed去掉 " 字符

代码语言:txt复制
sed -i 's/"//g' seg.txt

去掉换行符

代码语言:txt复制
echo $(seg.txt) > seg1.txt

3. 训练模型

3.1 训练word2vec模型

代码语言:txt复制
num_features = 300    # Word vector dimensionality
min_word_count = 10   # Minimum word count
num_workers = 16       # Number of threads to run in parallel
context = 10          # Context window size
downsampling = 1e-3   # Downsample setting for frequent words
sentences = word2vec.Text8Corpus("seg201708.txt")

model = word2vec.Word2Vec(sentences, workers=num_workers, 
        size=num_features, min_count = min_word_count, 
        window = context, sg = 1, sample = downsampling)
model.init_sims(replace=True)
# 保存模型
model.save("save_model")

# 可以在加载模型之后使用另外的语料库来进一步训练模型
# model = gensim.models.Word2Vec.load('save_model')
# model.train(more_sentences)

# load model
model = Word2Vec.load('save_model')     

参数说明:

sentences:可以是一个·ist,对于大语料集,建议使用BrownCorpus,Text8Corpus或ineSentence构建。 sg: 用于设置训练算法,默认为0,对应CBOW算法;sg=1则采用skip-gram算法。 size:是指特征向量的维度,默认为100。大的size需要更多的训练数据,但是效果会更好. 推荐值为几十到几百。 window:表示当前词与预测词在一个句子中的最大距离是多少 alpha: 是学习速率 seed:用于随机数发生器。与初始化词向量有关。 min_count: 可以对字典做截断. 词频少于min_count次数的单词会被丢弃掉, 默认值为5 max_vocab_size: 设置词向量构建期间的RAM限制。如果所有独立单词个数超过这个,则就消除掉其中最不频繁的一个。每一千万个单词需要大约1GB的RAM。设置成None则没有限制。 sample: 高频词汇的随机降采样的配置阈值,默认为1e-3,范围是(0,1e-5) workers参数控制训练的并行数。 hs: 如果为1则会采用hierarchica·softmax技巧。如果设置为0(defau·t),则negative sampling会被使用。 negative: 如果>0,则会采用negativesamp·ing,用于设置多少个noise words cbow_mean: 如果为0,则采用上下文词向量的和,如果为1(defau·t)则采用均值。只有使用CBOW的时候才起作用。 hashfxn: hash函数来初始化权重。默认使用python的hash函数 iter: 迭代次数,默认为5 trim_rule: 用于设置词汇表的整理规则,指定那些单词要留下,哪些要被删除。可以设置为None(min_count会被使用)或者一个接受()并返回RU·E_DISCARD,uti·s.RU·E_KEEP或者uti·s.RU·E_DEFAU·T的 sorted_vocab: 如果为1(defau·t),则在分配word index 的时候会先对单词基于频率降序排序。 batch_words:每一批的传递给线程的单词的数量,默认为10000

3.2 训练fasttext模型

FastText背后的主要原理是,单词的词法结构会携带有关单词含义的重要信息,而传统的单词嵌入并不会考虑这些信息,传统的单词嵌入会为每个单词训练一个唯一的单词嵌入。这对于形态丰富的语言(德语,土耳其语)尤其重要,在这种语言中,单个单词可能具有大量的形态形式,每种形态形式很少出现,因此很难训练良好的词嵌入。

FastText尝试通过将每个单词视为其子单词的集合来解决此问题。为了简单和独立于语言,将子词视为该词的字符n-gram(n元)。一个单词的向量被简单地认为是其组成特征图的所有向量之和。

与原始Word2Vec相比,FastText在语法任务上的表现要好得多,尤其是在训练语料库较小的情况下。在语义任务上,Word2Vec的性能略优于FastText。随着训练语料库大小的增加,差异变得越来越小。

FastText的训练时间明显长于Word2Vec的Gensim版本(15min 42s vs 6min 42s on text8, 17 mil tokens, 5 epochs, and a vector size of 100)。

总的来说,word2vec有一个很大的局限性,那就是该模型无法推断出不熟悉的单词的向量。如果这个限制了我们,那就尝试使用FastText模型。

代码语言:txt复制
from gensim.models.fasttext import FastText as FT_gensim
from gensim.test.utils import datapath
 
# Set file names for train and test data
corpus_file = datapath('corpus.txt')
 
model = FT_gensim(size=100)
 
# build the vocabulary
model.build_vocab(corpus_file=corpus_file)
 
# train the model
model.train(
    corpus_file=corpus_file, epochs=model.epochs,
    total_examples=model.corpus_count, total_words=model.corpus_total_words
)

# save/load model
import tempfile
import os
with tempfile.NamedTemporaryFile(prefix='saved_model_gensim-', delete=False) as tmp:
    model.save(tmp.name, separately=[])
 
loaded_model = FT_gensim.load(tmp.name)

参数介绍

相比w2v模型,fasttext还有一些参数:

min_n: char ngrams的最小长度 (默认 3) max_n: char ngrams的最大长度 (默认 6) bucket: 用于散列ngrams的buckets数量 (默认 200000)

4. 词向量使用

代码语言:txt复制
model.most_similar(positive=['woman', 'king'], negative=['man']) #根据给定的条件推断相似词
model.doesnt_match("breakfast cereal dinner lunch".split()) #寻找离群词
model.similarity('woman', 'man') #计算两个单词的相似度
model['computer'] #获取单词的词向量
model.most_similar(positive='奔驰',topn=10) # 最相近的词
similarity = model.n_similarity(['奥迪','特斯拉','大众','宾利'], ['促销','日产','奇骏']) # 词组距离
print(f"{similarity:.4f}")

5. Ref

  1. http://www.junphy.com/wordpress/index.php/2020/04/30/word2vec/
  2. https://github.com/duoergun0729/nlp/blob/master/自己动手训练word2vec模型.md
  3. https://blog.csdn.net/qq_38890412/article/details/104710375

0 人点赞