中文word2vec的python实现_基于Word2Vec的相似度计算(python)-Go语言中文社区

前言
此篇文章的基础知识部分总结了一些别人的文章解释,环境为Windows10下的python3.5版本,需要的包为gensim。代码很简要,不足之处请说明。
一. 背景知识
1.1词向量
词向量(word2vec)是一个将单词转换成向量形式的工具。可以把对文本内容的处理简化为向量空间中的向量运算,计算出向量空间上的相似度,来表示文本语义上的相似度。
在自然语言处理(NLP)相关任务中,要将自然语言交给机器学习中的算法来处理,通常需要首先将语言数学化,因为机器不是人,机器只认数学符号。向量是人把自然界的东西抽象出来交给机器处理的东西,基本上可以说向量是人对机器输入的主要方式了。
词向量就是用来将语言中的词进行数学化的一种方式,顾名思义,词向量就是把一个词表示成一个向量。NLP 中最直观,也是到目前为止最常用的词表示方法是 One-hot Representation,这种方法把每个词表示为一个很长的向量。这个向量的维度是词表大小,其中绝大多数元素为 0,只有一个维度的值为 1,这个维度就代表了当前的词。 在word2vec中则采用分布式表征,在向量维数比较大的情况下,每一个词都可以用元素的分布式权重来表示,因此,向量的每一维都表示一个特征向量,作用于所有的单词,而不是简单的元素和值之间的一一映射。
word2vec中包含了对两种模型的训练,C-BOW模型和Gensim模型。在训练每种模型的时候又分HS和NEG两种方法。除了google自己的word2vec工具,也有其它各自不同的版本。其中比较好用的是Python Gensim主题模型包中的word2vec,但通过python版本只实现了skip-gram模型,并且只实现了通过分层softmax方法对其训练,并没有使用negative sampling。
1.2语言模型
语言模型包括文法语言模型和统计语言模型。一般我们指的是统计语言模型。统计语言模型: 统计语言模型把语言(词的序列)看作一个随机事件,并赋予相应的概率来描述其属于某种语言集合的可能性。给定一个词汇集合 V,对于一个由 V 中的词构成的序列S = ?w1, · · · , wT ? ∈ Vn,统计语言模型赋予这个序列一个概率P(S),来衡量S 符合自然语言的语法和语义规则的置信度。用一句简单的话说,语言模型就是计算一个句子的概率大小。常见的统计语言模型有N元文法模型(N-gram Model),最常见的是unigram model、bigram model、trigram model等等。形式化讲,统计语言模型的作用是为一个长度为 m 的字符串确定一个概率分布 P(w1; w2; :::; wm),表示其存在的可能性,其中 w1 到 wm 依次表示这段文本中的各个词。本文所用到的语言模型为skip-gram,skip-gram模型的输入是一个单词wIwI,它的输出是wIwI的上下文wO,1,...,wO,CwO,1,...,wO,C,上下文的窗口大小为CC。
1.3 Gensim模块
本文用python进行预料的训练,其中用到模块Gensim,是一款开源的第三方Python工具包,用于从原始的非结构化的文本中,无监督地学习到文本隐层的主题向量表达。它支持包括TF-IDF,LSA,LDA,和word2vec在内的多种主题模型算法,支持流式训练,并提供了诸如相似度计算,信息检索等一些常用任务的API接口。
二. 训练预料的预处理
练语料的预处理指的是将文档中原始的字符文本转换成Gensim模型所能理解的稀疏向量的过程。Gensim的word2vec的输入是句子的序列. 每个句子是一个单词列表。
通常,我们要处理的原生语料是一堆文档的集合,每一篇文档又是一些原生字符的集合。在交给Gensim的模型训练之前,我们需要将这些原生字符解析成Gensim能处理的稀疏向量的格式。由于语言和应用的多样性,Gensim没有对预处理的接口做出任何强制性的限定。通常,我们需要先对原始的文本进行分词、去除停用词等操作,得到每一篇文档的特征列表。
本文的语料来源为wiki百科,共2M大小,选用Hanlp汉语分词系统进行文档的分词,
原始数据分词后,并去除词性标注以及停用词。
得到的使用数据结果如下图:
中文word2vec的python实现_基于Word2Vec的相似度计算(python)-Go语言中文社区
文章图片

Hanlp分词的主要代码如下图:
中文word2vec的python实现_基于Word2Vec的相似度计算(python)-Go语言中文社区
文章图片

三. 模型训练
3.1 代码以及参数设置
模型训练用到了pythpn中的Gensim模块,Gensim只要求输入按顺序提供句子, 并不将这些句子存储在内存, 然后Gensim可以加载一个句子, 处理该句子, 然后加载下一个句子.
Word2vec有很多可以影响训练速度和质量的参数:
(1) sg=1是skip-gram算法,对低频词敏感,默认sg=0为CBOW算法,所以此处设置为1。
(2) min_count是对词进行过滤,频率小于min-count的单词则会被忽视,默认值为5。
(3) size是输出词向量的维数,即神经网络的隐藏层的单元数。值太小会导致词映射因为冲突而影响结果,值太大则会耗内存并使算法计算变慢,大的size需要更多的训练数据, 但是效果会更好,在本文中设置的size值为300维度。
(4) window是句子中当前词与目标词之间的最大距离,即为窗口。本文设置窗口移动的大小为5。
(5) negative和sample可根据训练结果进行微调,sample表示更高频率的词被随机下采样到所设置的阈值,默认值为1e-3。
(6) hs=1表示层级softmax将会被使用,默认hs=0且negative不为0,则负采样将会被选择使用。
(7) 最后一个主要的参数控制训练的并行:worker参数只有在安装了Cython后才有效,由于本文没有安装Cython的, 使用的单核。
通过查看程序运行的日志记录,可看到参数设置如下所示:
中文word2vec的python实现_基于Word2Vec的相似度计算(python)-Go语言中文社区
文章图片

实现代码如下:
# -*- coding: utf-8 -*-
import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')
from gensim.models import word2vec
import logging
# 主程序
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.Text8Corpus(u"D:wiki语料.txt") # 加载语料
n_dim=300
# 训练skip-gram模型;
model = word2vec.Word2Vec(sentences, size=n_dim, min_count=5,sg=1)
# 计算两个词的相似度/相关程度
y1 = model.similarity(u"陕西省", u"山西省")
print(y1)
print("--------")
# 寻找对应关系
print(u"计算机-智能,速度-")
y3 = model.most_similar([u'智能', u'速度'], [u'计算机'], topn=3)
for item in y3:
print(item[0], item[1])
3.2存储和加载模型
存储、加载模型可以在加载模型之后继续使用句子来进一步训练模型。存储、加载模型的方法如下:
中文word2vec的python实现_基于Word2Vec的相似度计算(python)-Go语言中文社区
文章图片

3.3实验
本文进行了两项实验,一个是计算两个词的相似度/相关程度,另一个是通过给定的词语序列关系去寻找其它词语间的对应关系。本文计算了“陕西省”和“山西省”的相关程度,并且给定(计算机-智能,速度-)这样的一组关系得到了另一组关系,根据原有预料所训练的模型,实验结果如下如所示,可以看出“山西省”和“陕西省”的相似度很高约为0.954,同时通过给定的关系得出(水资源—降水,明显)这样一组关系
中文word2vec的python实现_基于Word2Vec的相似度计算(python)-Go语言中文社区
文章图片

四. 总结
【中文word2vec的python实现_基于Word2Vec的相似度计算(python)-Go语言中文社区】通过本次实验,了解到神经网络在自然语言中的运用,通过将语言数学化,达到计算机可以识别的地步。向量是人把自然界的东西抽象出来交给机器处理的东西,基本上可以说向量是人对机器输入的主要方式了。在本次试验中用到word2vct工具来计算相似度和寻找对应关系组,Word2vec包换两种语言模型一个是词袋模型另一个是skip-gram模型,但是这里用python进行编程,python版本下只有skip-gram模型,所以本文通过skip-gram来输出词语的权重,即300维的词向量。在输入数据之前,要对数据进行分词处理并去除停用词。模型训练完毕后,保存模型以便后续的使用或者完善。此次试验,加深了我对词向量的理解和运用,对于计算相似度的方法有了新的认识。

    推荐阅读