当前位置: 首页 > 科技观察

分词,难在哪里?-科普+解决方案!

时间:2023-03-19 17:25:39 科技观察

1.前言分词,我想是大多数前端大佬都不会接触到的概念。这不影响我们对它的理解,毕竟我们要向多个方向发展。今天,我将简单介绍一些分词。我会尽量用介绍性的语言来描述这个概念,最后提供解决方案。希望对您有所帮助。简单来说,分词就是根据词的意思把一个句子分成一个个的词。这么说可能意义不大,我们先看看它适用的场景。分词是文本挖掘的基础,通常用于自然语言处理、分词搜索、推荐等领域。2.分词的原理和算法2.1什么是分词首先要了解分词的概念。分词是将连续的词序列按照一定的规范重新组合成词序列的过程。在英语中,单词之间使用空格作为分隔符来分隔词与词,而对于中文,则没有明确的分隔符。正是因为缺少这样一个明确的分隔符,我们在分词的时候就会出现很多偏差。2.2分词算法中文分词难度较大,但已有成熟的解决方案。现有的分词算法大致可以分为三类:基于字符串匹配的分词算法基于理解的分词算法基于统计的分词算法1.基于字符串匹配的分词算法这种分词方法也称为机械分词算法.它会预先维护一个大字典,然后将句子与字典中的单词进行匹配。如果匹配成功,则可以进行分词。当然实际上会更复杂一些,因为当字典足够大的时候,会涉及到不同的匹配算法,这里就不多说了。通常基于Trie树结构,实现高效的词图扫描。2.基于理解的分词算法这种分词方法通过让计算机模拟人对句子的理解来达到识别词组的效果。其基本思想是在分词的同时分析句法和语义,利用句法和语义信息来处理歧义。它通常由三部分组成:分词子系统、句法语义子系统和通用控制部分。分词子系统在总控制部分的协调下,可以获取词、句子等的句法语义信息,判断分词的歧义,即模拟人对句子的理解过程。由于汉语语言知识的普遍性和复杂性,很难将各种语言信息组织成机器可以直接阅读的形式。因此,基于理解的分词系统还处于试验阶段。3.基于统计的分词算法这种方法会给出大量已经分词的文本,利用统计机器学习模型学习分词规则(称为训练),从而实现对未知文本的分词。随着大规模语料库的建立和统计机器学习方法的研究和发展,基于统计的中文分词方法逐渐成为主流方法。2.3分词的吸引力虽然分词的算法解释起来很简单,但是从现有的经验来看,几乎没有通用有效的分词系统。每个领域都有其独特的词汇表,这使得很难用有限的训练数据捕获所有语言特征。比如:通过人民日报培训的分词系统,在网络玄幻小说中分词效果就不会好。这是不可避免的。在分词系统中,没有灵丹妙药。不同的场景对分词的要求非常不同,通常可以从分词速度和分词准确率两个维度来区分。例如,分词搜索对速度的要求高于对准确性的要求。在一些问答系统中,需要对文本有更深入的理解,要求准确率高于速度。不同的领域、不同的使用场景对分词的要求是不同的,所以我们不能片面地理解分词的准确性。并且随着新词的增多和训练数据的变化,分词的准确率也在波动。这就是为什么吹嘘分词准确率的公司越来越少的原因。2.4分词解决方案分词是一种可以解决实际问题的功能。经过这么长时间的迭代更新,市场上已经产生了一批独具特色的分词系统。例如:IK、jieba、Ansj、Hanlp、Stanford分词等。有兴趣的可以一一了解。接下来,我将介绍开源库之一,jieba。3、jieba3.1的优点jieba是开源的,号称是Python中最好的中文分词组件。而且它是基于MIT协议的,所以你可以放心使用。jieba使用起来也很简单,几行代码就可以实现分词和词性标注,速度还不错。它内部维护着一本字典,是根据人民日报的分析得出的。词典外的新词将基于HMM模型进行识别。它提供三种分词模式:精确模式、完整模式和搜索模式。full模式是找到所有可能的词,search模式是在precise模式的基础上对长词进行切分,提高切分率。分词速度方面,精确模式可达400KB/s,全模式可达1.5MB/s。同时,除了Python版本,还有不同的人基于Python版本的jieba,扩展了多种语言的实现,包括:JavaScript、Java、Golang、R、PHP等。使用jieba的代码在jieba与Python2/3兼容。在使用之前,您需要使用命令pipinstalljieba或pip3installjieba安装它。具体的Api就不说了。有兴趣的可以查看Github上的文档(地址在文末)。下面通过一个简单的代码示例来感受一下jieba的方便和强大。#encoding=utf-8importjiebaseg_list=jieba.cut("我来到了北京清华",cut_all=True)print("FullMode:"+"/".join(seg_list))#fullmodeseg_list=jieba.cut("我来到北京清华",cut_all=False)print("DefaultMode:"+"/".join(seg_list))#精确模式seg_list=jieba.cut("他来到网易航研楼")#默认是精确模式print(",".join(seg_list))seg_list=jieba.cut_for_search("小明硕士毕业于中科院计算所,后赴日本京都大学留学")#搜索引擎模式print(",".join(seg_list))输出结果:[全模式]:I/come/Beijing/Tsinghua/TsinghuaUniversity/Huada/University[精模式]:me/come/Beijing/TsinghuaUniversity[新词识别】:他,来了Arrived,这里,网易,航研,大厦(这里“航研”在字典里没有,但维特比算法也能识别)【搜索引擎模型】:小明,硕士,研究生,于,中国,science,College,AcademyofSciences,ChineseAcademy,Computing,ComputingInstitute,After,In,Japan,Kyoto,University,KyotoUniversity,Japan前面说了jieba自己维护了一个词组字典,需要的话,有是专有名词需要拆分,也可以通过jieba.Tokenizer(dictionary=DEFAULT_DICT)加载自定义词典。3.2jieba的分词算法的匹配算法说起来复杂,这里简单介绍一下jieba分词匹配的原理。首先,jieba分词已经自带了一个dict.txt词典,里面有20000多条词条,包括出现次数和词性。这是笔者根据人民日报的数据自己训练的。jieba会先把这个字典中的数据放到一个Trie树中。Trie树是著名的前缀树。当一个词的前几个字符相同时,会认定它们有相同的前缀,可以使用Trie编号。它的优点是搜索速度快。其次,当需要对句子进行切分时,根据前面生成的Trie数生成有向无环图(DAG)。这一步的意义在于消除分词中的歧义,提高分词准确率,找出句子中所有可能的词。至此,字典中记录的所有单词的分词过程基本完成。但是如果删除字典dict.txt,jieba还是可以进行分词的,但是大部分分词的长度都是2。这是因为,对于没有被收录到字典中的词,使用维特比算法进行预测基于隐马尔可夫模型(HMM)的分词。在HMM模型中,汉语词汇按照BEMS的四种状态进行标注,B为起始位置,E为结束,为结束位置,M为middle,为中间位置,S为single,单个的位置一句话,无前无后。也就是说,他用(B、E、M、S)四种状态来标注中文单词。比如北京可以标为BE,即Bei/B京/E,表示Bei为起始位置,Beijing为结束位置,中华民族可以标为BMME,即开始,中间,中间和结尾。笔者通过大量语料训练得到了finalseg目录下的训练结果,有兴趣的可以自行研究。到这里基本就清楚了,jieba分词的过程主要有以下三个步骤:加载dict.txt字典,生成Trie树。对待分词句子,使用Trie树生成DAG图来匹配所有可能的词。然后使用HMM模型来匹配字典中没有收录的词。这就是jieba分词的执行过程。4.jieba(JavaorAndroid)4.1jiebajiebaJava版发展到现在,支持很多版本。Java版不是原作者自己写的,而是国家汉办参考原作者的分词原理开发的。不过Java版没有原来的Python版强大,做了一些阉割,比如没有实现关键词提取。有兴趣的可以直接上Github:https://github.com/huaban/jieba-analysis/1。引入依赖(稳定版)com.huabanjieba-analysis1.0.22.如何使用@TestpublicvoidtestDemo(){JiebaSegmentersegmenter=newJiebaSegmenter();String[]sentences=newString[]{“这是一个伸手不见五指的黑夜。我叫孙悟空,我爱北京,我爱Python和C++。","我不喜欢日本和服。","雷猴重出江湖","工信处女官,每个月路过下属部门都要亲自表白24次安装开关等技术设备","结果结婚未婚"};for(Stringsentence:sentences){System.out.println(segmenter.process(sentence,SegMode.INDEX).toString());}}3.性能评测笔者在测试机上测试,配置为:Processor2Intel(R)Pentium(R)CPUG620@2.60GHz内存:8GB测试结果还不错,单线程,测试文本逐行分词,循环调用数万效率分析。调用10000次第一次测试结果:timeelapsed:12373,rate:2486.986533kb/s,words:917319.94/s第二次测试结果:timeelapsed:12284,rate:2505.005241kb/s,words:923966.10/s第三次测试结果:timeelapsed:12336,rate:2494.445880kb/s,words:920071.30/s循环调用20000次第一个测试结果:timeelapsed:22237,rate:2767.593144kb/s,words:1020821.12/s第二个测试结果:timeelapsed:22435,rate:2743.167762kb/s,words:1011811.87/s第三次测试结果:timeelapsed:22102,rate:2784.497726kb/s,words:1027056.34/s统计结果:词典加载时间约1.8s,分词效率每秒超过2Mb,近100万字。2处理器Intel(R)Core(TM)i3-2100CPU@3.10GHz12G测试结果timeelapsed:19597,rate:3140.428063kb/s,words:1158340.52/stimeelapsed:20122,rate:3058.491639kb/s,words:1128118.44/s4.2inAndroid使用的是jiebajieba(Java)版本,还自带词典,所以在Android下引入会增加Apk的体积。同时,因为设备的配置,也会影响分词的效率。但是,如果你必须在Android设备上使用它,比如预处理搜索词,也是可以的。增加Apk的问题其实可以通过安装后下载字典来避免。jieba(java)是maven管理的,所以Gradle需要简单配置一下就可以支持了。1.配置build.gradlerepositories{google()jcenter()mavenCentral()}2.引入依赖实现'com.huaban:jieba-analysis:1.0.2'引入之后,使用细节就没什么好说的了,跟Java版本差异无关。参考:https://github.com/fxsjy/jiebahttps://github.com/huaban/jieba-analysis/https://blog.csdn.net/John_xyz/article/details/54645527http://www.infoq。com/cn/articles/nlp-word-segmentation【本文为专栏作家“张扬”原创稿件,转载请微信联系作者公众号获得授权】点此查看作者更多好文