分词的基础概念

为什么要进行分词

中文分词(Chinese Word Segmentation) 指的是将一个汉字序列切分成一个一个单独的词。

分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符,虽然英文也同样存在短语的划分问题,不过在词这一层上,中文比之英文要复杂的多、困难的多。

分词方法

  1. 基于字符串匹配的分词方法(机械分词法):将待分字串与词典进行匹配

    • 正向最大匹配法 (由左到右的方向)
    • 逆向最大匹配法(由右到左的方向)storage.blog.fliaping.com
    • 最小切分法(每句话切分的词数最少)
    • 双向最大匹配法(进行由左到右、由右到左两次扫描) Chinese-Word-Segmentation-arithmeti
  2. 基于理解(Semantic)的分词法:在分词的同时引入句法和语义信息处理歧义

  3. 基于统计的分词方法:相邻字频率越高越成词;多用于新词识别(补充词典)

  4. 复合分词法(上述3种方法的综合运用和相互补充)

那些高级的分词方法难度较大,所以用最简单的基于字符串匹配的分词方法,我们选择的mmseg4j分词器有Simple和Complex两种模式,都是基于正向最大匹配。

常用分词器介绍

  • mmseg4j 用 storage.blog.fliaping.comeg 算法(http://technology.chtsai.org/mmseg/ )实现的中文分词器,并实现 lucene 的 analyzer 和 solr 的TokenizerFactory 以方便在Lucene和Solr中使用,并且最后更新时间为2015年,支持Solr5。
  • IKAnalyzer,采用了特有的“正向迭代最细粒度切分算法“,具有60万字/秒的高速处理能力。采用了多子处理器分析模式,支持:英文字母、数字、中文词汇等分词处理,兼容韩文、日文字符。可以说IK也是很不错的分词器,不过由于他对Solr5兼容不是很好,所以最后也没用它。
  • paoding,Paoding’s Knives 中文分词具有极高效率和高扩展性 。引入隐喻,采用完全的面向对象设计,构思先进。但是已经很久不更新了。

下表出自中文分词器性能比较

整合mmseg4j到Solr5.5

下载:mmseg4j-solr

有很多个版本,支持Solr5的为mmseg4j-solr-2.3.0.jar,如果你在代码中使用还可以用maven仓库来直接添加依赖。要想整合进Solr,就需要另外的包mmseg4j-core-1.10.jar,其实mmseg4j-core这个包才是分词器的核心,mmseg4j-solr只是兼容Solr的接口。

放置jar包到正确位置

将这两个包放进servlet的类库目录中,这里的路径就是$Solr.Install.Dir/server/solr-webapp/webapp/WEB-INF/lib。如果你用的是Tomcat作为servlet,那么可以路径就应该是$TomcatDir/webapps/solr/WEB-INF/lib

创建一个SolrCore

首先保证Solr正常启动了,下面有三中创建方法。

  • 方法一:在命令行中新建。转到$Solr.Install.Dir,输入一下命令:
bin/solr create -c trip

成功可以看到如下输出日志

Copying configuration to new core instance directory:
/Users/Payne/Workspace/GraduateProject/Solr/solr-5.5.0/server/solr/trip

Creating new core 'trip' using command:
http://localhost:8983/solr/admin/cores?action=CREATE&name=trip&instanceDir=trip

{
  "responseHeader":{
    "status":0,
    "QTime":1217},storage.blog.fliaping.com
  "core":"trip"}
  • 方法二:在管理界面创建,首先在你的$SolrHome目录下建立要创建Core的文件夹,然后把同目录下的configsets/basic_configs/conf文件夹copy到你新建的Core文件夹中,之后再管理界面就可新建了,如下图所示。

create-new-core-useing-admin-ui * 方法三:在方法二copy完成配置文件的基础上,可以通过URL-API来创建,假如我要创建一个名为trip的core,可以用如下的链接

http://localhost:8983/solr/admin/cores?action=CREATE&name=trip&instanceDir=trip

如果创建成功页面中会返回

<response>
  <lst name="responseHeader">
    <int name="status">0</int>
    <int name="QTime">275</int>
  </lst>
  <str name="core">trip</str>
</response>

其实命令行创建就是把这个方法自动化的

修改配置文件

找到Core的配置文件夹,就是方法二中复制过来的那个,修改文件$SolrHome/trip/conf/managed-schema(在5.0前,该文件是shcema.xml,当然可以将该文件重命名为schema.xml,但不建议这么做),加入下面的内容并重启Solr,即可在Solr Admin 的console中看到新增的这些field了。

<!-- mmseg4j-->
    <field name="mmseg4j_complex_name" type="text_mmseg4j_complex" indexed="true" stored="true"/>
    <field name="mmseg4j_maxword_name" type="text_mmseg4j_maxword" indexed="true" stored="true"/>
    <field name="mmseg4j_simple_name" type="text_mmseg4j_simple" indexed="true" stored="true"/>

    <fieldType name="text_mmseg4j_complex" class="solr.TextField" positionIncrementGap="100" >
       <analyzer>
          <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex" dicPath="/Users/Payne/Workspace/GitHub/trip-search/SolrHome/trip/conf"/>
          <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
        </analyzer>
    </fieldType>
    <fieldType name="text_mmseg4j_maxword" class="solr.TextField" positionIncrementGap="100" >
         <analyzer>
           <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="max-word" dicPath="/Users/Payne/Workspace/GitHub/trip-search/SolrHome/trip/conf"/>
           <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
         </analyzer>
     </fieldType>
     <fieldType name="text_mmseg4j_simple" class="solr.TextField" positionIncrementGap="100" >
        <analyzer>
           <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="simple" dicPath="/Users/Payne/Workspace/GitHub/trip-search/SolrHome/trip/conf"/>
           <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
         </analyzer>
     </fieldType>
<!-- mmseg4j-->storage.blog.fliaping.com

这里要注意dicPath,是这个tokenizer的词库文件的路径,最好用绝对位置。

重启Solr 后,即可在新创建的trip这个core的Analysis中看到mmseg4j新增的field。 show-mmseg4j-field-added

停用词字典

概念: >在信息检索中,为节省存储空间和提高搜索效率,在处理自然语言数据(或文本)之前或之后会自动过滤掉某些字或词,这些字或词即被称为Stop Words(停用词)。

停用词分为两类:功能词和词汇词。在这里我们不做区分,主要是屏蔽一些如”是,的,地,得”等一些功能性的词汇。

编辑配置目录中的stopwords.txt文件,添加停用词,每个词占一行。添加了如下停用词之后(记得要重启Solr哦),对九寨沟的水真是美丽极了这句话分词的结果如图所示,看到所分出来的词的,真是在停用词文件中有匹配,所以被屏蔽掉了。

是
的
啊storage.blog.fliaping.com
哈
嗯
真是

the-water-of-jiuzhaogou-is-so-beautifu

增加词库

mmseg4j默认是使用mmseg4j-core-1.10.0.jar中的words.dic,总共只有不到15万的中文词,另外我做的是旅游搜索,所以会有很多地名、经典名之类的专有词,所以,我们还需要另外增加词库。这些词库已经有很多现成的资源可以供我们使用,各大输入法厂商都有专有名词包供我们下载,但它们一般都是私有的二进制格式,不是文本文件,所幸有人做了词库转换软件,我们可以下载输入法的词库文件然后转成文本。

将做好的词库文件命名为word.dic,放在前面dicPath配置的文件夹下,我这里就放在SolrHome的conf目录下。(名字一定要是word.dic)

重启Solr,再次进行Analysis,这次关闭了详细参数的显示。

至此,已经完成mmseg4j的整合。

complex和maxword两种类型的区别

引用自: Solr 5.x的搭建(Solr自带的Jetty Server)与mmseg4j中文分词

我们假定我们的分词库中存在着”林书豪“,”书豪“,”林书“3个词。 在mmseg4j-complex算法中,”林书豪”会被完整分词为”林书豪”,而mmseg4j-maxword中由于只支持两个字的分词,“林书豪”会被分词为“林书”,“书豪”。这也就以为这如果你选的是mmseg4j-complex算法,你要搜索出含有“林书豪”的内容,则你必须完整的输入“林书豪”才会能够搜得出结果,而在mmseg4j-maxword算法中,你只需要输入“林书”或者“书豪”就可以得出想要的结果了。

所以在实际开发过程中,我们常常需要在精度和广度之间得出权衡的时候,可以选择性的丰富词库,更改词库,比我我希望输入“林书”或者“书豪”的时候就可以得到我想要的结果,那么我就可以在词库中加入“林书”和“书豪”,并且使用mmseg4j-maxword算法,但是我希望的是输入完整的林书豪才能得到我希望的搜索结果,那么就需要使用mmseg4j-complex算法,而且词库中需要加入“林书豪”。

注意:

  • 在words.dic中分词的顺序是很重要的,比如对于上面的例子“林书豪来中国了”,如果选择mmseg4j-complex算法,并且在词库的最后加入“来中国”,那么你可以看到分词的结果为后面的”来中国“将替代前面的“中国”。