现有分词介绍:
自然语言处理是一个信息时代最重要的技术之一,简单来讲,就是让计算机能够理解人类语言的一种技术。在其中,分词技术是一种比较基础的模块。对于英文等拉丁语系而言,由于词之间有空格作为词边际表示,词语一般情况下都能简单且准确的提取出来。而中文等文字,除了标点符号以外,字之间紧密相连,没有明显的词边界,因此很难将词提取出来。分词的意义非常大,在中文中,单字作为最基本的语义单位,虽然也有自己的意义,但表意能力较差,意义较分散,而词的表意能力更强,能更加准确的描述一个事物,因此在自然语言处理中,通常情况下词(包括单字成词)是最基本的处理单位。在具体的应用上,比如在常用的搜索引擎中,term如果是词粒度的话,不仅能够减少每个term的倒排列表长度,提升系统性能,并且召回的结果相关性高更准确。比如搜索query”的确”,如果是单字切分的话,则有可能召回”你讲的确实在理”这样的doc。分词方法大致分为两种:基于词典的机械切分,基于统计模型的序列标注切分两种方式。
基于词典的方法:
基于词典的方法本质上就是字符串匹配的方法,将一串文本中的文字片段和已有的词典进行匹配,如果匹配到,则此文字片段就作为一个分词结果。但是基于词典的机械切分会遇到多种问题,最为常见的包括歧义切分问题和未登录词问题。
歧义切分:
歧义切分指的是通过词典匹配给出的切词结果和原来语句所要表达的意思不相符或差别较大,在机械切分中比较常见,比如下面的例子:“结婚的和尚未结婚的人”,通过机械切分的方式,会有两种切分结果:1,“结婚/的/和/尚未/结婚/的/人”;2,“结婚/的/和尚/未/结婚/的/人”。可以明显看出,第二种切分是有歧义的,单纯的机械切分很难避免这样的问题。
未登录词识别:
未登录词识别也称作新词发现,指的是词没有在词典中出现,比如一些新的网络词汇,如“网红”,“走你”;一些未登录的人名,地名;一些外语音译过来的词等等。基于词典的方式较难解决未登录词的问题,简单的case可以通过加词典解决,但是随着字典的增大,可能会引入新的bad case,并且系统的运算复杂度也会增加。
基于词典的机械分词改进方法:
为了解决歧义切分的问题,在中文分词上有很多优化的方法,常见的包括正向最大匹配,逆向最大匹配,最少分词结果,全切分后选择路径等多种算法。
最大匹配方法:
正向最大匹配指的是从左到右对一个字符串进行匹配,所匹配的词越长越好,比如“中国科学院计算研究所”,按照词典中最长匹配原则的切分结果是:“中国科学院/计算研究所”,而不是“中国/科学院/计算/研究所”。但是正向最大匹配也会存在一些bad case,常见的例子如:“他从东经过我家”,使用正向最大匹配会得到错误的结果:“他/从/东经/过/我/家”。
逆向最大匹配的顺序是从右向左倒着匹配,如果能匹配到更长的词,则优先选择,上面的例子“他从东经过我家”逆向最大匹配能够得到正确的结果“他/从/东/经过/我/家”。但是逆向最大匹配同样存在badcase:“他们昨日本应该回来”,逆向匹配会得到错误的结果“他们/昨/日本/应该/回来”。
针对正向逆向匹配的问题,将双向切分的结果进行比较,选择切分词语数量最少的结果。但是最少切分结果同样有bad case,比如“他将来上海”,正确的切分结果是“他/将/来/上海”,有4个词,而最少切分结果“他/将来/上海”只有3个词。
全切分路径选择方法:
全切分方法就是将所有可能的切分组合全部列出来,并从中选择最佳的一条切分路径。关于路径的选择方式,一般有n最短路径方法,基于词的n元语法模型方法等。
n最短路径方法的基本思想就是将所有的切分结果组成有向无环图,每个切词结果作为一个节点,词之间的边赋予一个权重,最终找到权重和最小的一条路径作为分词结果。
基于词的n元语法模型可以看作是n最短路径方法的一种优化,不同的是,根据n元语法模型,路径构成时会考虑词的上下文关系,根据语料库的统计结果,找出构成句子最大模型概率。一般情况下,使用unigram和bigram的n元语法模型的情况较多。
基于序列标注的分词方法:
针对基于词典的机械切分所面对的问题,尤其是未登录词识别,使用基于统计模型的分词方式能够取得更好的效果。基于统计模型的分词方法,简单来讲就是一个序列标注问题。
在一段文字中,我们可以将每个字按照他们在词中的位置进行标注,常用的标记有以下四个label:B,Begin,表示这个字是一个词的首字;M,Middle,表示这是一个词中间的字;E,End,表示这是一个词的尾字;S,Single,表示这是单字成词。分词的过程就是将一段字符输入模型,然后得到相应的标记序列,再根据标记序列进行分词。举例来说:“达观数据位是企业大数据服务商”,经过模型后得到的理想标注序列是:“BMMESBEBMEBME”,最终还原的分词结果是“达观数据/是/企业/大数据/服务商”。
在NLP领域中,解决序列标注问题的常见模型主要有HMM和CRF。
HMM
HMM(HiddenMarkov Model)隐马尔科夫模型应用非常广泛,基本的思想就是根据观测值序列找到真正的隐藏状态值序列。在中文分词中,一段文字的每个字符可以看作是一个观测值,而这个字符的词位置label(BEMS)可以看作是隐藏的状态。使用HMM的分词,通过对切分语料库进行统计,可以得到模型中5大要要素:起始概率矩阵,转移概率矩阵,发射概率矩阵,观察值集合,状态值集合。在概率矩阵中,起始概率矩阵表示序列第一个状态值的概率,在中文分词中,理论上M和E的概率为0。转移概率表示状态间的概率,比如B->M的概率,E->S的概率等。而发射概率是一个条件概率,表示当前这个状态下,出现某个字的概率,比如p(人|B)表示在状态为B的情况下人字的概率。
有了三个矩阵和两个集合后,HMM问题最终转化成求解隐藏状态序列最大值的问题,求解这个问题最长使用的是Viterbi算法,这是一种动态规划算法,具体的算法可以参考维基百科词条,在此不详细展开。(https://en.wikipedia.org/wiki/Viterbi_algorithm)
CRF
CRF(Conditionalrandom field,条件随机场)是用来标注和划分结构数据的概率化结构模型,通常使用在模式识别和机器学习中,在自然语言处理和图像处理等领域中得到广泛应用。和HMM类似,当对于给定的输入观测序列X和输出序列Y,CRF通过定义条件概率P(Y|X),而不是联合概率分布P(X,Y)来描述模型。CRF算法的具体算法可以参考维基百科词条。(https://en.wikipedia.org/wiki/Conditional_random_field)
在实际应用中有很多工具包可以使用,比如CRF++,CRFsuite,SGD,Wapiti 等,其中CRF++的准确度较高。在分词中使用CRF++时,主要的工作是特征模板的配置。CRF++支持unigram,bigram两种特征,分别以U和B开头。举例来讲U00:%x[-2,0]表示第一个特征,特征取值是当前字的前方第二个字,U01:%x[-1,0]表示第二个特征,特征取值当前字前一个字,U02:%x[0,0]表示第三个特征,取当前字,以此类推。特征模板可以支持多种特征,CRF++会根据特征模板提取特征函数,用于模型的建立和使用。特征模板的设计对分词效果及训练时间影响较大,需要分析尝试找到适用的特征模板。
深度学习介绍
随着AlphaGo的大显神威,Deep Learning(深度学习)的热度进一步提高。深度学习来源于传统的神经网络模型。传统的神经网络一般由输入层,隐藏层,输出层组成,其中隐藏层的数目按需确定。深度学习可以简单的理解为多层神经网络,但是深度学习的却不仅仅是神经网络。深度模型将每一层的输出作为下一层的输入特征,通过将底层的简单特征组合成为高层的更抽象的特征来进行学习。在训练过程中,通常采用贪婪算法,一层层的训练,比如在训练第k层时,固定训练好的前k-1层的参数进行训练,训练好第k层之后的以此类推进行一层层训练。
深度学习在很多领域都有所应用,在图像和语音识别领域中已经取得巨大的成功。从2012年开始,LSVRC(LargeScale Visual Recognition Challenge)比赛中,基于Deep Learningd计算框架一直处于领先。2015年LSVRC(http://www.image-net.org/challenges/LSVRC/2015/results)的比赛中,微软亚洲研究院(MSRA)在图像检测(Objectdetection),图像分类定位(Object Classification+localization)上夺冠,他们使用的神经网络深达152层。
在NLP中的应用
在自然语言处理上,深度学习在机器翻译、自动问答、文本分类、情感分析、信息抽取、序列标注、语法解析等领域都有广泛的应用。2013年末google发布的word2vec工具,可以看做是深度学习在NLP领域的一个重要应用,虽然word2vec只有三层神经网络,但是已经取得非常好的效果。通过word2vec,可以将一个词表示为词向量,将文字数字化,更好的让计算机理解。使word2vec模型,我们可以方便的找到同义词或联系紧密的词,或者意义相反的词等。
P.S:word2vec的安装:
word2vec
要解决问题: 在神经网络中学习将word映射成连续(高维)向量,这样通过训练,就可以把对文本内容的处理简化为K维向量空间中向量运算,而向量空间上的相似度可以用来表示文本语义上的相似度。
一般来说, word2vec输出的词向量可以被用来做很多 NLP 相关的工作,比如聚类、找同义词、词性分析等等。另外还有其向量的加法组合算法。官网上的例子是 :
vector(‘Paris’) - vector(‘France’) +
vector(‘Italy’) ≈vector(‘Rome’), vector(‘king’) - vector(‘man’) + vector(‘woman’) ≈
vector(‘queen’)
但其实word2vec也只是少量的例子完美符合这种加减法操作,并不是所有的 case 都满足。
快速入门
1、从http://word2vec.googlecode.com/svn/trunk/ 下载所有相关代码:
一种方式是使用svn Checkout,可加代理进行check。
另一种就是export to github,然后再github上下载,我选择第二种方式下载。
2、运行make编译word2vec工具:(如果其中makefile文件后有.txt后缀,将其去掉)在当前目录下执行make进行编译,生成可执行文件(编译过程中报出很出Warning,暂且不管);
3、运行示例脚本:./demo-word.sh 看一下./demo-word.sh的内容,大致执行了3步操作
从http://mattmahoney.net/dc/text8.zip 下载了一个文件text8 ( 一个解压后不到100M的txt文件,可自己下载并解压放到同级目录下);
使用文件text8进行训练,训练过程比较长;
执行word2vec生成词向量到 vectors.bin文件中,(速度比较快,几分钟的事情)
在demo-word.sh中有如下命令
time ./word2vec -train text8 -output vectors.bin -cbow 1 -size 200 -window 8 -negative 0 -hs 1 -sample 1e-4 -threads 20 -binary 1 -iter 15
time ./word2vec -train text8 -output vectors.bin -cbow 1 -size 200 -window 8 -negative 0 -hs 1 -sample 1e-4 -threads 20 -binary 1 -iter 15
以上命令
-train text8 表示的是输入文件是text8
-output vectors.bin 输出文件是vectors.bin
-cbow 1 表示使用cbow模型,默认为Skip-Gram模型
-size 200 每个单词的向量维度是200
-window 8 训练的窗口大小为5就是考虑一个词前八个和后八个词语(实际代码中还有一个随机选窗口的过程,窗口大小小于等于8)
-negative 0 -hs 1不使用NEG方法,使用HS方法。-
sampe指的是采样的阈值,如果一个词语在训练样本中出现的频率越大,那么就越会被采样。
-binary为1指的是结果二进制存储,为0是普通存储(普通存储的时候是可以打开看到词语和对应的向量的)
-iter 15 迭代次数
demo-word.sh中最后一行命令是./distance vectors.bin
该命令是计算距离的命令,可计算与每个词最接近的词了:
word2vec还有几个参数对我们比较有用比如-alpha设置学习速率,默认的为0.025. –min-count设置最低频率,默认是5,如果一个词语在文档中出现的次数小于5,那么就会丢弃。-classes设置聚类个数,看了一下源码用的是k-means聚类的方法。要注意-threads 20 线程数也会对结果产生影响。
架构:skip-gram(慢、对罕见字有利)vs CBOW(快)
训练算法:分层softmax(对罕见字有利)vs 负采样(对常见词和低纬向量有利)
欠采样频繁词:可以提高结果的准确性和速度(适用范围1e-3到1e-5)
文本(window)大小:skip-gram通常在10附近,CBOW通常在5附近
4、运行命令 ./demo-phrases.sh:查看该脚本内容,主要执行以下步骤:
从http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2012.en.shuffled.gz 下载了一个文件news.2012.en.shuffled.gz ( 一个解压到1.7G的txt文件,可自己下载并解压放到同级目录下);
将文件中的内容拆分成 phrases,然后执行./word2vec生成短语向量到 vectors-phrase.bin文件中(数据量大,速度慢,将近半个小时),如下:
最后一行命令./distance vectors-phrase.bin,一个计算word相似度的demo中去,结果如下:
结果好坏跟训练词库有关。
番外:
如果需要中文语料库,推荐使用维基的或者搜狗(http://www.sogou.com/labs/dl/ca.html),中文分词可使用结巴分词,我觉得很好用。然后进行训练,因为英文不用分词,所以上述过程不涉及分词。
本文主要偏应用,讲解一个例子,便于对word2vec有一个初步了解,后续再更原理。
{
http://www.sogou.com/labs/resource/ca.php针对下载的搜狗的语料库,如何将dat转换txt
然后用这个提取出来就好了
}