word2vec 단어 벡터 훈련 및 중국어 텍스트 유사성 계산

이 글은 word2vec 사용법에 대한 기본적인 튜토리얼입니다. 상대적으로 기본적인 글인데 도움이 되셨으면 좋겠습니다!
공식 홈페이지 C 언어 다운로드 주소: http://word2vec.googlecode.com/svn/trunk/
공식 홈페이지 Python 다운로드 주소: http://radimrehurek.com/gensim/models/word2vec.html


1. 간략한 소개


참고: "Word2vec의 핵심 아키텍처 및 응용 · Xiong Fulin, Deng Yihao, Tang Xiaosheng · 베이징 우편 통신 대학 2015" "Word2vec의 작동 원리 및 응용에 관한 연구 · Zhou Lian · Xi'an 전자 과학 대학
          및 Technology 2014" "
          Word2vec을 이용한 중국어 단어 클러스터링 연구 · Zheng Wenchao, Xu Peng · 베이징 우편 통신 대학 2013》

PS: 첫 번째 부분은 주로 기본적인 내용을 소개하는 것입니다. 그러한 기사가 많이 있습니다. 더 많은 기본 콘텐츠를 스스로 배워 보세요. 이 블로그는 주로 중국어 텍스트에 대한 Word2Vec의 사용법을 소개하는 블로그입니다.

(1) 통계적 언어 모델
통계적 언어 모델의 일반적인 형태는 알려진 단어 집합이 주어졌을 때 다음 단어의 조건부 확률을 푸는 것입니다. 형태는 다음과 같습니다.


통계적 언어모델의 일반적인 형태는 직관적이고 정확하며, n-gram 모델에서는 문맥상 단어의 순서를 바꾸지 않으면서 서로 가까운 단어 간의 관계가 가까울수록 멀어지는 것으로 가정한다. 멀리 있는 단어 사이의 관계 거리가 충분히 멀면 단어 사이에는 상관 관계가 없습니다.

그러나 이 모델은 말뭉치의 정보를 충분히 활용하지 못한다.
1) 더 멀리 있는 단어와 현재 단어 사이의 관계를 고려하지 않는다. 관련이 있습니다.
예를 들어, "Washington is the capital of the United States"가 현재 문장이고, "Beijing is the capital of China"가 n 단어 이상 뒤에 나타납니다. n-ary 모델에서 "Washington"과 "Beijing"은 그렇지 않습니다. 그러나 이 두 문장은 문법적, 의미적 관계를 함축하고 있는데, 즉 "Washington"과 "Beijing"은 모두 명사이며 각각 미국과 중국의 수도이다.

2) 단어 간의 유사성은 무시됩니다. 즉, 위 모델에서는 단어의 문법적 관계를 고려할 수 없습니다.

예를 들어, 말뭉치의 "fish swim in the water"는 "horses running on the 초원"과 같은 문장을 생성하는 데 도움이 됩니다. 왜냐하면 두 문장에는 "fish"와 "horse", "water"와 "grassland"가 있고, "수영"은 "달리다", "중", "상"과 같은 문법적 특성을 가지고 있습니다.
신경망 확률적 언어 모델에서는 이 두 가지 정보가 완벽하게 활용됩니다.

(2) 신경망 확률적 언어 모델
신경망 확률적 언어 모델은 새롭게 떠오르는 자연어 처리 알고리즘으로 훈련 코퍼스를 학습하여 단어 벡터와 확률 밀도 함수를 구하며, 단어 벡터는 다차원 실수 벡터이고, 벡터에는 자연어가 포함되어 있으며, 단어 사이의 의미적, 문법적 관계, 단어 벡터 사이의 코사인 거리의 크기는 단어 사이의 관계의 거리를 나타내며, 단어 벡터의 가감은 컴퓨터가 "단어를 선택하여 문장을 만드는 것"입니다.

신경망 확률론적 언어 모델은 오랜 개발 단계를 거쳤는데, 2003년 Bengio 등이 제안한 신경망 언어 모델 NNLM(Neural Network Language Model)이 가장 유명하며 향후 개발 작업에서는 이 모델을 참고할 예정이다. 10년 이상의 연구 끝에 신경망 확률적 언어 모델은 큰 발전을 이루었습니다.
요즘에는 아키텍처 측면에서 NNLM보다 간단한 CBOW 모델과 Skip-gram 모델이 있으며, 둘째, 훈련 측면에서는 Hierarchical Softmax 알고리즘과 Negative Sampling 알고리즘(Negative Sampling)이 등장하고 있으며, 정확도를 낮추기 위해 자주 사용되는 단어쌍과 훈련 속도의 영향으로 도입된 서브샘플링 기술


위 그림은 3계층 신경망을 기반으로 한 자연어 추정 모델 NNLM(Neural Network Language Model)입니다. NNLM은 특정 컨텍스트의 다음 단어가 wi, 즉 (wi=i|context)일 확률을 계산할 수 있으며, 단어 벡터는 해당 훈련의 부산물입니다. NNLM은 코퍼스 C를 기반으로 해당 어휘 V를 생성합니다.

일반 네트워크에 대한 지식은 내 이전 블로그를 참조하세요. 신경망 및 기계 학습 기본 소개
Rachel-Zhang의 NNLM 추천 기사 공유: word2vec - 효율적인 단어 특징 추출
최근 몇 년 동안 신경망 확률 언어 모델이 빠르게 발전했습니다. , 그리고 Word2vec은 최신 기술의 이론 모음입니다.
Word2vec은 Google이 2013년에 공개한 단어 벡터 훈련용 소프트웨어 도구입니다. 따라서 word2vec에 대해 이야기하기 전에 먼저 단어 벡터의 개념에 대해 소개하겠습니다.

(3) 단어 벡터
참조: licstar의 NLP 기사  Deep Learning in NLP (1) 단어 벡터 및 언어 모델
저자가 말했듯이: 딥 러닝 알고리즘은 이미지 및 오디오 분야에서 놀라운 결과를 달성했지만 아직 NLP에서는 성공하지 못했습니다. 필드. 정말 흥미로운 결과를 볼 수 있습니다. 언어(단어, 문장, 장 등)는 인간의 인지 과정에서 생성되는 높은 수준의 인지적 추상 개체인 반면, 음성과 이미지는 낮은 수준의 원래 입력 신호이므로 후자 두 가지가 더 적합하다는 말이 있습니다. 딥러닝을 위한 학습 기능.
하지만 단어를 '단어 벡터' 형태로 표현하는 것은 딥러닝 알고리즘을 NLP 분야에 도입하는 핵심 기술이라고 할 수 있다. 자연어 이해 문제를 머신러닝 문제로 전환하는 첫 번째 단계는 이러한 기호를 방법을 통해 수학적으로 수학화하는 것입니다.

词向量具有良好的语义特性,是表示词语特征的常用方式。词向量的每一维的值代表一个具有一定的语义和语法上解释的特征。故可以将词向量的每一维称为一个词语特征。词向量用Distributed Representation表示,一种低维实数向量。
例如,NLP中最直观、最常用的词表示方法是One-hot Representation。每个词用一个很长的向量表示,向量的维度表示词表大小,绝大多数是0,只有一个维度是1,代表当前词。
“话筒”表示为 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 …] 即从0开始话筒记为3。
但这种One-hot Representation采用稀疏矩阵的方式表示词,在解决某些任务时会造成维数灾难,而使用低维的词向量就很好的解决了该问题。同时从实践上看,高维的特征如果要套用Deep Learning,其复杂度几乎是难以接受的,因此低维的词向量在这里也饱受追捧。
Distributed Representation低维实数向量,如:[0.792, −0.177, −0.107, 0.109, −0.542, …]。它让相似或相关的词在距离上更加接近。

总之,Distributed Representation是一个稠密、低维的实数限量,它的每一维表示词语的一个潜在特征,该特征捕获了有用的句法和语义特征。其特点是将词语的不同句法和语义特征分布到它的每一个维度上去表示。
推荐我前面的基础文章:Python简单实现基于VSM的余弦相似度计算


(4) Word2vec
参考:Word2vec的核心架构及其应用 · 熊富林,邓怡豪,唐晓晟 · 北邮2015年
Word2vec是Google公司在2013年开放的一款用于训练词向量的软件工具。它根据给定的语料库,通过优化后的训练模型快速有效的将一个词语表达成向量形式,其核心架构包括
CBOW和Skip-gram。

在开始之前,引入模型复杂度,定义如下:
                                                      O = E * T * Q
其中,E表示训练的次数,T表示训练语料中词的个数,Q因模型而异。E值不是我们关心的内容,T与训练语料有关,其值越大模型就越准确,Q在下面讲述具体模型是讨论。

NNLM模型是神经网络概率语言模型的基础模型。在NNLM模型中,从隐含层到输出层的计算时主要影响训练效率的地方,CBOW和Skip-gram模型考虑去掉隐含层。实践证明新训练的词向量的精确度可能不如NNLM模型(具有隐含层),但可以通过增加训练语料的方法来完善。
Word2vec包含两种训练模型,分别是CBOW和Skip_gram(输入层、发射层、输出层),如下图所示:


CBOW模型:
理解为上下文决定当前词出现的概率。在CBOW模型中,上下文所有的词对当前词出现概率的影响的权重是一样的,因此叫CBOW(continuous bag-of-words model)模型。如在袋子中取词,取出数量足够的词就可以了,至于取出的先后顺序是无关紧要的。

Skip-gram模型:
Skip-gram模型是一个简单实用的模型。为什么会提出该问题呢?
在NLP中,语料的选取是一个相当重要的问题。
首先,语料必须充分。一方面词典的词量要足够大,另一方面尽可能地包含反映词语之间关系的句子,如“鱼在水中游”这种句式在语料中尽可能地多,模型才能学习到该句中的语义和语法关系,这和人类学习自然语言是一个道理,重复次数多了,也就会模型了。
其次,语料必须准确。所选取的语料能够正确反映该语言的语义和语法关系。如中文的《人民日报》比较准确。但更多时候不是语料选取引发准确性问题,而是处理的方法。
由于窗口大小的限制,这会导致超出窗口的词语与当前词之间的关系不能正确地反映到模型中,如果单纯扩大窗口大小会增加训练的复杂度。Skip-gram模型的提出很好解决了这些问题。


Skip-gram表示“跳过某些符号”。例如句子“中国足球踢得真是太烂了”有4个3元词组,分别是“中国足球踢得”、“足球踢得真是”、“踢得真是太烂”、“真是太烂了”,句子的本意都是“中国足球太烂”,可是上面4个3元组并不能反映出这个信息。
此时,使用Skip-gram模型允许某些词被跳过,因此可组成“中国足球太烂”这个3元词组。如果允许跳过2个词,即2-Skip-gram,那么上句话组成的3元词组为:


由上表可知:一方面Skip-gram反映了句子的真实意思,在新组成的这18个3元词组中,有8个词组能够正确反映例句中的真实意思;另一方面,扩大了语料,3元词组由原来的4个扩展到了18个。
语料的扩展能够提高训练的准确度,获得的词向量更能反映真实的文本含义。


2.下载源码


下载地址:http://word2vec.googlecode.com/svn/trunk/
使用SVN Checkout源代码,如下图所示。





3.中文语料


PS:最后附有word2vec源码、三大百科语料、腾讯新闻语料和分词python代码。
中文语料可以参考我的文章,通过Python下载百度百科、互动百科、维基百科的内容。
        [python] lantern访问中文维基百科及selenium爬取维基百科语料
        [Python爬虫] Selenium获取百度百科旅游景点的InfoBox消息盒

下载结果如下图所示,共300个国家,百度百科、互动百科、维基百科各自100个,对应的编号都是0001.txt~0100.txt,每个txt中包含一个实体(国家)的信息。


然后再使用Jieba分词工具对齐进行中文分词和文档合并。
#encoding=utf-8
import sys
import re
import codecs
import os
import shutil
import jieba
import jieba.analyse

#导入自定义词典
jieba.load_userdict("dict_all.txt")

#Read file and cut
def read_file_cut():    
    #create path
    pathBaidu = "BaiduSpiderCountry\\"
    resName = "Result_Country.txt"
    if os.path.exists(resName):
        os.remove(resName)
    result = codecs.open(resName, 'w', 'utf-8')

    num = 1
    while num<=100:  #5A 200 其它100
        name = "%04d" % num 
        fileName = pathBaidu + str(name) + ".txt"
        source = open(fileName, 'r')
        line = source.readline()
        
        while line!="":
            line = line.rstrip('\n')
            #line = unicode(line, "utf-8")
            seglist = jieba.cut(line,cut_all=False)  #精确模式
            output = ' '.join(list(seglist))         #空格拼接
            #print output
            result.write(output + ' ')               #空格取代换行'\r\n'
            line = source.readline()
        else:
            print 'End file: ' + str(num)
            result.write('\r\n')  
            source.close()
        num = num + 1
    else:
        print 'End Baidu'
        result.close()

#Run function
if __name__ == '__main__':
    read_file_cut()

上面只显示了对百度百科100个国家进行分词的代码,但核心代码一样。同时,如果需要对停用词过滤或标点符号过滤可以自定义实现。
分词详见: [python] 使用Jieba工具中文分词及文本聚类概念
分词合并后的结果为Result_Country.txt,相当于600行,每行对应一个分词后国家。





4.运行源码


强烈推荐三篇大神介绍word2vec处理中文语料的文章,其中Felven好像是师兄。
        Windows下使用Word2vec继续词向量训练 - 一只鸟的天空
        利用word2vec对关键词进行聚类 - Felven
        http://www.52nlp.cn/中英文维基百科语料上的word2vec实验
        word2vec 词向量工具 - 百度文库

因为word2vec需要linux环境,所有首先在windows下安装linux环境模拟器,推荐cygwin。然后把语料Result_Country.txt放入word2vec目录下,修改demo-word.sh文件,该文件默认情况下使用自带的text8数据进行训练,如果训练数据不存在,则会进行下载,因为需要使用自己的数据进行训练,故注释掉下载代码。

demo-word.sh文件修改如下:
make
#if [ ! -e text8 ]; then
#  wget http://mattmahoney.net/dc/text8.zip -O text8.gz
#  gzip -d text8.gz -f
#fi
time ./word2vec -train Result_Country.txt -output vectors.bin -cbow 1 -size 200 -window 8 -negative 25 -hs 0 -sample 1e-4 -threads 20 -binary 1 -iter 15
./distance vectors.bin

下图参数源自文章:Windows下使用Word2vec继续词向量训练 - 一只鸟的天空


运行命令sh demo-word.sh,等待训练完成。模型训练完成之后,得到了vectors.bin这个词向量文件,可以直接运用。




5.结果展示


通过训练得到的词向量我们可以进行相应的自然语言处理工作,比如求相似词、关键词聚类等。其中word2vec中提供了distance求词的cosine相似度,并排序。也可以在训练时,设置-classes参数来指定聚类的簇个数,使用kmeans进行聚类。
cd C:/Users/dell/Desktop/word2vec
sh demo-word.sh
./distance vectors.bin 

输入阿富汗:喀布尔(首都)、坎大哈(主要城市)、吉尔吉斯斯坦、伊拉克等。

输入国歌:


输入首都:

输入GDP:


最后希望文章对你有所帮助,主要是使用的方法。同时更多应用需要你自己去研究学习。
word2vec源码、语料下载地址:
        http://download.csdn.net/detail/eastmount/9434889
(By:Eastmount 2016-02-18 深夜1点  http://blog.csdn.net/eastmount/ )

추천

출처blog.csdn.net/Eastmount/article/details/50637476