Solr中文分词及分数计算

Solr中文分词及分数计算

中文分词

基本概念

众所周知,英文是以词为单位的,词与词之间是靠空格隔开,而中文是以字为单位,句子中所有的字连起来才能表达清楚意思。举个例子,英文句子I am a student,用中文表示“我是一个学生”。如果是处理英文的话,计算机可以通过空格知道student是一个单词,但是不能够识别出学生为一个词。

把中文的汉字序列切分成有意义的词,就是中文分词,也可以称为切词。

应用场景

目前在自然语言处理技术中,中文处理技术要比西方处理技术落后很大一段距离,很多西文的处理方法对中文不能直接采用,主要原因就是中文必须有分词,中文分词是处理中文信息的基础。

搜索引擎是中文分词最常见也是最典型的的应用,分词的准确性对搜索引擎十分重要,同时分词的速度也一样重要,分词过慢或是分词错误会严重影响到搜索引擎使用时的体验,因此对于搜索引擎来说速度和准确性都需要达到很高的要求。

搜索引擎能快速检索到查询的关键字,主要得益于他采用的数据存储机制,“倒排索引”,而倒排索引的前提是中文分词,只有通过中文分词才能识别出词语,然后创建索引。

分词类型

分词技术现在已经非常成熟,主要分为3种技术:

1.基于词典的字符串匹配分词

​ 按照一定的策略将待匹配的字符串与词库中的词条进行匹配,若在词典中找到对应的字符串,则匹配成功。

​ 根据扫描方向的不同,可以分为正向匹配和反向匹配

​ 根据不同长度有限匹配的情况,可分为最大匹配和最小匹配

​ 常见的匹配方法有:正向最大匹配,逆向最大匹配,最短路径最大匹配

接下来举个例子:

匹配词条为“研究生命起源”,词库中包含“研究”、“研究生”、“生命”、“起源”

正向最大匹配:首先会匹配到“研究生”,然后是“命”,最后是“起源”

备选词 词典是否存在 分词结果 长度最大匹配结果
研究生
研究 研究
研究生 研究生
研究生命
研究生命起
命起
命起源
起源
起源 起源

逆向最大匹配:首先会匹配到“起源”,然后是“生命”,最后是“研究”

备选词 词典是否存在 分词结果 长度最大匹配结果
起源
起源 起源
命起源
生命起源
究生命起源
生命
生命 生命
究生命
研究生命
研究
研究 研究

2.基于统计的分词方法

该方法主要通过统计上下文中相邻的字同时出现的次数,次数越多,就与可能构成一个词。这种方法只需要对语料中的字组频率进行统计,不需要切分词典,因而又叫做无词典分词,但是这种方法存在很多风险,比如经常会匹配出一些高频但不是词的字组,对词的识别度差,开销较大。

实际应用的统计分词系统都要使用一部基本的分词词典(常用词词典)进行串匹配分词,同时使用统计方法识别一些新的词,即将串频统计和串匹配结合起来,既发挥匹配分词切分速度快、效率高的特点,又利用了无词典分词结合上下文识别生词、自动消除歧义的优点。

3.基于语法的分词方法

由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式,因此目前基于理解的分词系统还处在试验阶段。

分词难题

尽管分词技术很成熟,但由于汉语的复杂性,仍有两个问题有待突破

1.歧异识别

  • 交叉歧异

    比如“化妆和服装”,可以分为“化妆|和服|装”、“化妆|和|服装”

  • 组合歧异

    比如“门把手坏了”和“请把手拿开”,一个是动词,一个是名词

  • 真歧异

    比如“乒乓球拍卖完了”,可以分为“乒乓球|拍卖|完|了”和“乒乓球拍|卖|完|了”

2.新词识别

​ 除了人名,还有机构、地名、产品名等新词,但这些又是顺应时代所产生的词汇,使用频率也会很高。

IK中文分词器

分词方法

Ik分词器采用正向迭代最细粒度切分算法,属于正向最大匹配算法的衍生。

相对最大匹配算法进行了一定程度的优化,接上边“研究生命起源”进行分析:

备选词词典是否存在分词结果长度最大匹配结果
研究生
研究研究
研究生研究生
研究生命
研究生命起
生命
生命生命
生命起源
起源
起源起源

内部包含两种分词方法:智能和非智能

智能分词会分出“研究|生命|起源”

非智能分词则会分出“研究|研究生|生命|起源”

词库配置

我使用的ik分词器是github上边的一个源码https://github.com/magese/ik-analyzer-solr

当前这个分词器支持外置扩展词库的配置、solr7、solr8,版本支持高,然后重新配置了自己的词库。

IK分词器允许用户自定义三种词库:扩展词库ext.dic,停用词库stopword.dic和同义词库synonyms.txt。词库格式必须都是非BOM的UTF-8

扩展词库 每个扩展词占一行,在jar包中配置即可,效果同主词库

停用词库 每个停用词占一行,主要作用是过滤一些不需要分词的特殊字段,在jar包中配置即可

同义词库 同义词库通过配置managed-schema文件,在相应字段下面添加同义词匹配的条件,词库设置有两种格式,一种是通过=>连接两个词汇,不能处理多个词语同义,还有就是多个词汇通过英文逗号(,)隔开即可,文件在solr服务下面。

当前情况若是词库更新的话还需要重启服务,并重新构建索引,不满足上线需求,因此又添加了扩展词库动态加载,源代码中新增每隔一分钟自动检查词库是否更新机制,主要是通过ik.conf文件中的lastUpdate字段,每次更新之后字段加1即可,然后服务便会自动重新加载主词库和扩展词库,避免了每次新增词汇重启服务的繁琐操作。

搭建过程中的注意事项
  1. 索引和查询的配置

    索引按照最新颗粒度进行创建,查询按照最大颗粒度进行创建

    颗粒度的配置在solr6以前是按照isMaxLength来进行配置,从solr6开始按照useSmart来进行配置,也就是上面所说的智能分词和非智能分词,这样分词可以加大检索的准确性。

    managed-schema文件中ik分词器基本配置如下:

    在这里插入图片描述

  2. 动态词库的配置

    在添加新词之后同时需要修改配置文件中的数值,动态词库和配置文件都需要放到对应的集合下面的配置文件夹里面

    ik.conf文件说明:

    files为动态词典列表,可以设置多个词典表,用逗号进行分隔,默认动态词典表为dynamicdic.txt;

    lastupdate默认值为0,每次对动态词典表修改后请+1,不然不会将词典表中新的词语添加到内存中。

    lastupdate采用的是int类型,不支持时间戳,要使用时间戳把源码中的int改成long即可。

  3. 主词库、停词库与同义词库的配置

    正常情况来说主词库的词条数量越大,匹配效果越好,但也有一个弊端就是匹配出来的结果会有很多,为了能够更准确的显示查询结果,我们需要将当前语料中的词语进行适当切分并添加到词库中,另外同义词库中的词语在主词库或者扩展词库中必须存在,不然会导致查询同义词时导致查询词进行了分词而未达到同义词检索的效果。

    停用词配置时一定要确定该字段确实不需要分词,否则到时候该字段在检索时会被直接过滤,会影响检索结果。

排序分值计算

算法简介

Solr本身的排序打分规则是继承自 Lucene的文本相关度的打分即boost,这一套算法对于通用的提供全文检索的服务来讲,已经够用了,但是对于一些专门领域的搜索来讲,文本相关度的 打分是不合适的。

Lucene算法公式如下

在这里插入图片描述

tf(t in d ) = frequency½,频率,定义为t出现在文档中的次数d
idf(t) = 1 + log(numDocs/(docFreq + 1)),逆文档频率,numDocs为文档总数,docFreq为包含t的文档数
coord(q, d) 评分因子,。越多的查询项在一个文档中,说明些文档的匹配程序越高,比如说,查询"A B C",那么同时包含A/B/C3个词的文档 是3分,只包含A/B的文档是2分,coord可以在query中关掉的
queryNorm(q)查询的标准查询,使不同查询之间可以比较,不会影响文档排名
t.getBoost() 和 norm(t,d) 都是提供的可编程接口,可以调整 field/文档/query项 的权重
queryNorm(q) = 1 / (sumOfSquaredWeights ) 欧里几得范数
sumOfSquaredWeights = q.getBoost()2 • ∑ ( idf(t) • t.getBoost() )2 
norm(t,d) = d.getBoost() • lengthNorm(f) • f.getBoost() 
lengthNorm(field) = (1.0 / Math.sqrt(numTerms)):一个域中包含的Term总数越多,也即文档越长,此值越小,文档越短,此值越大。

除了TF-IDF求取相似度之外,Solr还内置了BM25、DFR、IB、LMDirichlet、LMJelinekMercer、Schema等算法。

规则修改

可以通过修改tf-idf的规则,使得结果呈现的效果更加符合预期,可以在ik分词器源码中写一个继承自ClassicSimilarity类的方法,然后重写tf、idf方法,然后在manage-schema(schema.xml)中将ik的相似度实现替换成你所写的类,然后重启solr服务即可。

如下:我不想受tf和idf的影响,都最终结果都改为1
在这里插入图片描述
在这里插入图片描述

相关文章

Solr7.1.0部署到tomcat

总结

本文首先简单介绍了中文分词的基本原理,然后结合ik分词器自定义词库的配置,另外对lucene中tf-idf的算法做了简单的了解,最后通过重写源码方法实现自己的排序。本文是我查看众多博客和文档,然后结合自己的理解进行的记录,有不当之处欢迎指出。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值