中文分词——知更鸟分词(RS)设计与实现
内容提要
- 1 分词概述
- 2 算法分类
- 2.1 字符匹配
- 2.2 理解法
- 2.3 统计法
- 3 常见项目
- 4 知更鸟分词实现
- 4.1 算法描述
- 4.2 数据结构
- 4.3 部分代码
- 4.4 运行结果
- 5 对比验证
- 5.1 分词速度对比
- 5.2 分词结果对比
- 6 总结
本文设计了一种带逆向回退策略的正向最大匹配。
1 分词概述
英文文本的处理相对简单,每一个单词之间有空格或标点符号隔开。如果不考虑短语,仅以单词作为唯一的语义单元的话,处理英文单词切分相对简单,只需要分类多有单词,去除标点符号。中文自然语言处理首先要解决的难题就是中文分词技术。
中文分词(Chinese Word Segmentation) 指的是将一个汉字序列切分成一个个单独的词。分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。
2 算法分类
现有的分词算法可分为三大类:基于字符串匹配的分词方法、基于理解的分词方法和基于统计的分词方法。按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与标注相结合的一体化方法。
2.1 字符匹配
这种方法又叫做机械分词方法,它是按照一定的策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。按照扫描方向的不同,串匹配分词方法可以分为正向匹配和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配。
常用的几种机械分词方法如下:
1)正向最大匹配法(由左到右的方向);
2)逆向最大匹配法(由右到左的方向);
3)最少切分(使每一句中切出的词数最小);
4)双向最大匹配法(进行由左到右、由右到左两次扫描)
2.2 理解法
这种分词方法是通过让计算机模拟人对句子的理解,达到识别词的效果。其基本思想就是在分词的同时进行句法、语义分析,利用句法信息和语义信息来处理歧义现象。它通常包括三个部分:分词子系统、句法语义子系统、总控部分。在总控部分的协调下,分词子系统可以获得有关词、句子等的句法和语义信息来对分词歧义进行判断,即它模拟了人对句子的理解过程。这种分词方法需要使用大量的语言知识和信息。由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式,因此目前基于理解的分词系统还处在试验阶段。
2.3 统计法
从形式上看,词是稳定的字的组合,因此在上下文中,相邻的字同时出现的次数越多,就越有可能构成一个词。因此字与字相邻共现的频率或概率能够较好的反映成词的可信度。可以对语料中相邻共现的各个字的组合的频度进行统计,计算它们的互现信息。定义两个字的互现信息,计算两个汉字X、Y的相邻共现概率。互现信息体现了汉字之间结合关系的紧密程度。当紧密程度高于某一个阈值时,便可认为此字组可能构成了一个词。这种方法只需对语料中的字组频度进行统计,不需要切分词典,因而又叫做无词典分词法或统计取词方法。但这种方法也有一定的局限性,会经常抽出一些共现频度高、但并不是词的常用字组,例如“这一”、“之一”、“有的”、“我的”、“许多的”等,并且对常用词的识别精度差,时空开销大。实际应用的统计分词系统都要使用一部基本的分词词典(常用词词典)进行串匹配分词,同时使用统计方法识别一些新的词,即将串频统计和串匹配结合起来,既发挥匹配分词切分速度快、效率高的特点,又利用了无词典分词结合上下文识别生词、自动消除歧义的优点。
3 常见项目
极易分词(JE)
MMAnalyzer极易中文分词组件,由中科院提供的中文极易分词器。比较完善的中文分词器。
支持英文、数字、中文(简体)混合分词。
常用的数量和人名的匹配。
超过22万词的词库整理。
实现正向最大匹配算法。
IKAnalyzer(IK)
IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的IKAnalyzer3.0则发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。
Paoding(PD)
Paoding(庖丁解牛分词)基于Java的开源中文分词组件,提供lucene和solr 接口,具有极 高效率和 高扩展性。引入隐喻,采用完全的面向对象设计,构思先进。
高效率:在PIII 1G内存个人机器上,1秒可准确分词 100万汉字。
采用基于不限制个数的词典文件对文章进行有效切分,使能够将对词汇分类定义。
能够对未知的词汇进行合理解析。
仅支持Java语言。
MMSEG4J(MS)
MMSEG4J基于Java的开源中文分词组件,提供lucene和solr 接口:
1.mmseg4j 用 Chih-Hao Tsai 的 MMSeg 算法实现的中文分词器,并实现 lucene 的 analyzer 和 solr 的TokenizerFactory 以方便在Lucene和Solr中使用。
2.MMSeg 算法有两种分词方法:Simple和Complex,都是基于正向最大匹配。Complex 加了四个规则过虑。官方说:词语的正确识别率达到了 98.41%。mmseg4j 已经实现了这两种分词算法。
smallseg(SS)
开源的,基于DFA的轻量级的中文分词工具包。
特点:可自定义词典、切割后返回登录词列表和未登录词列表、有一定的新词识别能力。
4 知更鸟分词实现
中文分词既然作为自然语言处理的基本工具,那么我们就来实现一个基于字符匹配的中文分词,用我的英文名(Robin)给她起个名字,就叫做——知更鸟分词器(RS/Robin-Segmenter)。
4.1 算法描述
基本实现算法:
(1)正向最大匹配;
(2)逆向最大匹配;
(3)逆向回退策略的正向最大匹配(重点)。
支持以下功能:
- 新词发现、新词标注;
- 字符转换、格式统一;
- 自定义分割符;
- 特殊符号保留;
- 检索分词模式;
- 合并拆分模式;
4.2 数据结构
基于字典字符匹配匹配的分词算法,重点是字典数据结构的设计。好的字典数据结构能够极大提升匹配检索的效率。
采用基本容器HashMap实现的一种变种字典树(Trie)结构。其基本的思想如图。
Trie树型结构之正向最大匹配过程
假设词典:中国 | 中南海 | 人民 | 人民币 | 人情 | 银行 | 中国人民 | 中国人民银行 | 中国人寿保险 | ……
例如:“中国人民银行行长易纲。”这样一条文本的匹配过程如图示红线路径。分词结果应该示“中国人民银行 行长 易纲”。
由于中文词首字分布比较均匀,并且查询首字的概率远大于其他非首字,根节点采用map数组方式,数组下标为字符的Unicode码减去最小中文汉字 Unicode码。数组维度为汉字的Unicode码范围。
4.3 部分代码
Unicode工具类:
package com.robin.segment.robinseg;import com.robin.config.ConfigUtil;
import com.robin.file.FileUtil;
import java.util.HashSet;
import java.util.Set;/*** <DT><B>描述:</B></DT>* <DD>Unicode 编码工具类</DD>** @version Version1.0* @author Robin* @version <I> V1.0 Date:2018-01-28</I>* @author <I> E-mail:xsd-jj@163.com</I>*/
public class Unicode {/** 量词配置路径 */private static final String QUANTIFIER_PATH;/** 量词集合 */private static Set<Character> quantifierSet;/** 中文数词路径 */private static final String NUMERAL_PATH;/** 中文数词集合 */private static Set<Character> numeralSet;/** 词典文件编码 */private static final String DIC_ENCODING;/** 空字符 Unicode */public static final int NULL = 0x0;/** 半角空格 Unicode */public static final int DBC_BLANK = 0x20;/** 半角句点 Unicode */public static final int DBC_POINT = 0x2E;/** 半角0 Unicode */public static final int DBC_0 = 0x30;/** 半角9 Unicode */public static final int DBC_9 = 0x39;/** 半角A Unicode */public static final int DBC_A = 0x41;/** 半角Z Unicode */public static final int DBC_Z = 0x5A;/** 半角a Unicode */public static final int DBC_LA = 0x61;/** 半角z Unicode */public static final int DBC_LZ = 0x7A;/** 普通最小中文汉字 Unicode */public static final int MIN_CHINESE = 0x4E00;/** 普通最大中文汉字 Unicode */public static final int MAX_CHINESE = 0x9FA5;/** 全角空格 Unicode */public static final int SBC_BLANK = 0x3000;//0xFF00也是全角空格/** 关注全角下限 Unicode */public static final int SBC_LOW_LIMIT = 0xFF00;/** 关注全角上限 Unicode */public static final int SBC_UP_LIMIT = 0xFF5E;/** 全角句点 Unicode */public static final int SBC_POINT = 0xFF0E;/** 全角0 Unicode */public static final int SBC_0 = 0xFF10;/** 全角9 Unicode */public static final int SBC_9 = 0xFF19;/** 全角A Unicode */public static final int SBC_A = 0xFF21;/** 全角Z Unicode */public static final int SBC_Z = 0xFF3A;/** 全角a Unicode */public static final int SBC_LA = 0xFF41;/** 全角z Unicode */public static final int SBC_LZ = 0xFF5A;/** 半角全角数字或字母 Unicode 编码偏移 */public static final int OFFSET_DBC_SBC = 0xFEE0;/** 英文大小写字母 Unicode 编码偏移 */public static final int OFFSET_UP_LOW = 0x20;static {QUANTIFIER_PATH = ConfigUtil.getConfig("dic.quantifier");NUMERAL_PATH = ConfigUtil.getConfig("dic.numeral");DIC_ENCODING = ConfigUtil.getConfig("dic.encoding");initQantifierSet();initNumeralSet();}/*** Unicode 字符类型*/public enum CharType {/** 控制符 */CONTROL,/** 半角数字 */DBC_DIGIT,/** 半角大写字母 */DBC_UPPER_CASE,/** 半角小写字母 */DBC_LOWER_CASE,/** 中文 */COMMON_CHINESE,/** 全角字符 */SBC_CHAR,/** 全角字母 */SBC_CASE,/** 全角数字 */SBC_DIGIT,/** 全角大写字母 */SBC_UPPER_CASE,/** 全角小写字母 */SBC_LOWER_CASE,/** 小数点 */DECIMAL_POINT,/** 数字后缀 */DECIMAL_SUFFIX,/** 百分比符号 */PERCENT_CHAR,/** 空白符 */BLANK_CHAR,/** 其他 */OTHER_CHAR,}/*** 通过字符判断其类型** @param ch Unicode字符* @return 字符类型*/public static CharType getCharType(char ch) {int value = ch;//Unicode 普通中文汉字区if ((value >= MIN_CHINESE) && (value <= MAX_CHINESE)) {return CharType.COMMON_CHINESE;}//空白符、控制字符、半角空格0x20、全角空格0x3000if ((value <= DBC_BLANK) || (value == SBC_BLANK)) {return CharType.BLANK_CHAR;}//半角数字0-9:0x30-0x39if ((value >= DBC_0) && (value <= DBC_9)) {return CharType.DBC_DIGIT;}//半角字母a-z:0x61-0x7Aif ((value >= DBC_LA) && (value <= DBC_LZ)) {return CharType.DBC_LOWER_CASE;}//半角字母A-Z:0x41-0x5Aif ((value >= DBC_A) && (value <= DBC_Z)) {return CharType.DBC_UPPER_CASE;}//小数点:半角0x2Eif (value == DBC_POINT) {return CharType.DECIMAL_POINT;}//数字后缀if ((value == (int) ('%'))|| (value == (int) ('$'))|| (value == (int) ('¥'))) {return CharType.DECIMAL_SUFFIX;}//关注的全角区:0xFF00-0xFF5E 与半角相距FEE0if ((value >= SBC_LOW_LIMIT) && (value <= SBC_UP_LIMIT)) {return CharType.SBC_CHAR;}//说明:全角其他子区可以不判断了,为扩展保留//全角数字0-9:0xFF10-0xFF19 与半角相距FEE0if ((value >= SBC_0) && (value <= SBC_9)) {return CharType.SBC_CHAR;}//全角字母A-Z:0xFF21-0xFF3A 与半角相距FEE0if ((value >= SBC_A) && (value <= SBC_Z)) {return CharType.SBC_CHAR;}//全角字母a-z:0xFF41-0xFF5A 与半角相距FEE0if ((value >= SBC_LA) && (value <= SBC_LZ)) {return CharType.SBC_CHAR;}//其他字符return CharType.OTHER_CHAR;}/*** 判断字符否是数字类型字符。** @param ch 字符* @return boolean true-数字类型,fasle-非数字类型*/static boolean isDecimalType(char ch) {if (Unicode.isDecimal(ch)) {return true;}if (Unicode.isPoint(ch)) {return true;}return Unicode.isDecimalSuffix(ch);}/*** 判断字符否是数字。** @param ch 字符* @return boolean true-数字,fasle-非数字*/static boolean isDecimal(char ch) {int unicode = ch;//半角或全角数字return ((unicode >= DBC_0) && (unicode <= DBC_9))|| (unicode >= SBC_0) && (unicode <= SBC_9);}/*** 判断字符是否是数字后缀。** @param ch 字符* @return boolean true-数字后缀,false-非数字后缀*/static boolean isDecimalSuffix(char ch) {int unicode = ch;//数字后缀return (unicode == (int) ('%'))|| (unicode == (int) ('$'))|| (unicode == (int) ('¥'));}/*** 判断字符是否是小数点。** @param ch 字符* @return boolean true-小数点,fasle-非小数点*/static boolean isPoint(char ch) {int unicode = ch;//半角或全角数字return (unicode == DBC_POINT) || (unicode == SBC_POINT);}/*** 初始化中文数字集合*/private static void initNumeralSet() {numeralSet = new HashSet<>();String numerals = FileUtil.readText(NUMERAL_PATH, DIC_ENCODING);char[] symbolArr = numerals.toCharArray();for (int i = 0; i < symbolArr.length; i++) {numeralSet.add(symbolArr[i]);}}/*** 判断一个字符是否是中文数字** @param ch 输入字符* @return 是否是中文数字*/static boolean isNumeral(char ch) {int unicode = ch;if ((unicode < Unicode.MIN_CHINESE) || (unicode > Unicode.MAX_CHINESE)) {return false;}return numeralSet.contains(ch);}/*** 初始化单量词集合*/private static void initQantifierSet() {quantifierSet = new HashSet<>();String quantifiers = FileUtil.readText(QUANTIFIER_PATH, DIC_ENCODING);char[] symbolArr = quantifiers.toCharArray();for (int i = 0; i < symbolArr.length; i++) {quantifierSet.add(symbolArr[i]);}}/*** 判断一个字符是否是中文量词** @param ch 输入字符* @return 是否是量词*/static boolean isQuantifier(char ch) {int unicode = ch;if ((unicode < Unicode.MIN_CHINESE) || (unicode > Unicode.MAX_CHINESE)) {return false;}return quantifierSet.contains(ch);}
}
分词器参数配置:
package com.robin.segment.robinseg;/*** <DT><B>描述:</B></DT>* <DD>Robin分词器参数配置类</DD>** @version 1.0* @author Robin* @version <I> V1.0 Date:2018-01-30</I>* @author <I> E-mail:xsd-jj@163.com</I>*/
public class SegmentArgs {/** 词结束符 */static final char END_MARK = Unicode.NULL;/** 分词方法 */SegAlgorithm segMethod = SegAlgorithm.FORWARD;/** 符号标志 */boolean cleanSymbolFlag = true;/** 新词标注标志 */boolean markNewWordFlag = false;/** 大小写转换 */boolean downCasingFlag = true;/** 分词合并模式-字典中未出现的孤立子合并 */boolean mergePatternFlag = true;/** 分词检索模式 */boolean retrievalPatternFlag = false;/** 分隔符 */String separator = " ";/** 词标符号 */private static final String WORD_MARK = "⊙";/** 新词标记 */static final String NEW_WORD_MARK = "[" + WORD_MARK + "新词]";/** 拼接词标记 */static final String SPLICE_WORD_MARK = "[" + WORD_MARK + "拼接词]";/** 混合词标记 */static final String CN_EN_MIX_MARK = "[" + WORD_MARK + "混合词]";/*** Robin分词方法枚举类型*/public enum SegAlgorithm {/** 带回退策略的正向最大匹配 */FORWARD,/** 简单反向最大匹配 */REVERSE}/*** 词的类别*/enum WordClass {STANDARD,/** 英文词,自动识别 */ENGLISH,/** 数量词,包括自动识别的中文数量词 */QUANTIFIER,/** 新词,识别的含有中文字符的新词 */NEW_WORD,/** 中英文混合词 */CN_EN_MIX,/** 拼接新词,标准词与孤立字符拼接出来的新词 */SPLICE_WORD,/** 孤立中文字符 */ISOLATED_CN,/** 其他,上述之外 */OTHER}/*** 构造方法*/public SegmentArgs() {}/*** 重置默认配置参数*/public void resetDefaultArgs() {this.segMethod = SegAlgorithm.FORWARD;this.cleanSymbolFlag = true;this.markNewWordFlag = false;this.downCasingFlag = true;this.mergePatternFlag = true;this.retrievalPatternFlag = false;}/*** 设置分词分隔符** @param separator 分隔符*/void setSeparator(String separator) {this.separator = separator;}/*** 设置删除符号标志** @param flag 是否删除*/public void setCleanSymbolFlag(boolean flag) {this.cleanSymbolFlag = flag;}/*** 设置是否检索型分词** @param flag 是否检索型分词*/public void setRetrievalPatternFlag(boolean flag) {this.retrievalPatternFlag = flag;}/*** 设置拼接模式标志** @param flag 是否拼接模式*/public void setMergePatternFlag(boolean flag) {this.mergePatternFlag = flag;}/*** 设置新词标注开关** @param flag 是否标注*/public void setMarkNewWordFlag(boolean flag) {this.markNewWordFlag = flag;}/*** 设置分词算法 目前支持正向最大匹配、反向最大匹配 分词算法修改需要重新加载词典** @param segAlgorithm 分词算法*/public void setSegAlgorithm(SegAlgorithm segAlgorithm) {this.segMethod = segAlgorithm;}/*** 设置是否大-小写字母转换** @param flag 是否转换*/public void setDowncasingFlag(boolean flag) {this.downCasingFlag = flag;}
}
词典类:
package com.robin.segment.robinseg;import com.robin.config.ConfigUtil;
import com.robin.log.RobinLogger;
import com.robin.file.FileUtil;
import com.robin.segment.robinseg.Unicode.CharType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;/*** <DT><B>描述:</B></DT>* <DD>词典类</DD>** @version Version1.0* @author Robin* @version <I> V1.0 Date:2018-01-28</I>* @author <I> E-mail:xsd-jj@163.com</I>*/
class Dictionary {private static final Logger LOGGER = RobinLogger.getLogger();// 词典路径private static final String DIC_PATH;// 词典文件编码private static final String DIC_ENCODING;// 词典MapTreeprivate static Map<Character, Object> reverseDicMap = null;// 词典MapTree数组private static Map[] forwardDicArr = null;static {DIC_PATH = ConfigUtil.getConfig("dic.base");if (DIC_PATH == null) {LOGGER.log(Level.SEVERE, "dictionary file path config err.");}String encoding = ConfigUtil.getConfig("dic.encoding");if (null == encoding) {DIC_ENCODING = "UTF-8";} else {DIC_ENCODING = encoding;}loadForwardDictionary();loadReverseDictionary();}static Map<Character, Object> getReverseDicMap() {return reverseDicMap;}static Map[] getForwardDicArr() {return forwardDicArr;}/*** 加载正向词典mapTree数组*/private static void loadForwardDictionary() {if (null != forwardDicArr){return;}//代码略LOGGER.log(Level.INFO, "Load forward dictionary successfully.");}/*** 加载反向词典mapTree*/private static void loadReverseDictionary() {if (null != reverseDicMap) {return;}// 代码略LOGGER.log(Level.INFO, "Load reverse dictionary successfully.");}/*** 获取分词全字符字典** @return 分词字典*/public String getDicAllTrems() {buildTrems(reverseDicMap);return dicBuilder.toString();}private List<Character> wordList = new ArrayList<>();private StringBuilder dicBuilder = new StringBuilder();/*** 递归构建全字符词典** @param map Map + Tree 格式词典*/private void buildTrems(Map<Character, Object> map) {if (null == map) {for (int i = 0; i < wordList.size(); i++) {Character character = wordList.get(i);dicBuilder.append(character);}dicBuilder.append("\n");return;}Iterator<Character> it = map.keySet().iterator();while (it.hasNext()) {Character character = it.next();wordList.add(character);Map<Character, Object> nextMap = (Map<Character, Object>) map.get(character);buildTrems(nextMap);wordList.remove(wordList.size() - 1);}}
}
分词器部分代码:
package com.robin.segment.robinseg;import com.robin.segment.robinseg.SegmentArgs.SegAlgorithm;
import com.robin.segment.AbstractSegmenter;
import com.robin.segment.robinseg.SegmentArgs.WordClass;
import com.robin.segment.robinseg.Unicode.CharType;
import java.util.Map;/*** <DT><B>描述:</B></DT>* <DD>Robin分词类</DD>* <DD>实现:正向最大匹配算法,反向最大匹配(simple)</DD>* <DD>默认:带逆向回退策略的正向最大匹配</DD>** @version Version1.0* @author Robin* @version <I> V1.0 Date:2018-01-28</I>* @author <I> E-mail:xsd-jj@163.com</I>*/
public class RobinSeg extends AbstractSegmenter {//分词实例private static AbstractSegmenter instance = null;//分词配置项private static final SegmentArgs SEG_CONG = new SegmentArgs();//遍历字符序列的标记前一记录private Record last = new Record();//遍历字符序列的标记当前记录private Record curr = new Record();//存放已经分好词的序列private StringBuilder splited;// 当前最大索引(已经扫描到的最前索引,主要用于检索分词)private int currMaxIndex = -1;private final Map[] forwardDicArr;private final Map<Character, Object> reverseDicMap;/*** 构造方法*/private RobinSeg() {forwardDicArr = Dictionary.getForwardDicArr();reverseDicMap = Dictionary.getReverseDicMap();}/*** * @return*/public SegmentArgs getSegmentConfInstance() {return SEG_CONG;}/*** 调用具体分词方法** @param text 输入待分词文本* @param separator 分隔符* @return 已分词文本*/@Overridepublic String segment(String text, String separator) {synchronized (this) {if (SEG_CONG.segMethod.equals(SegAlgorithm.FORWARD)) {return forwardMaxMatch(text, separator);} else if (SEG_CONG.segMethod.equals(SegAlgorithm.REVERSE)) {return reverseMaxMatch(text, separator);}}assert false : "算法类型参数错误,检查参数设置。";return "";}/*** 词的记录私有类*/private class Record {//词的类别WordClass wordClass = WordClass.OTHER;//以一个字符开头一条字符序列最多可能形成的词的数目,先估计最大不超过10个private static final int MAX_NUM = 10;int start = 0;int maxIdx = -1;int[] end = new int[MAX_NUM];boolean continued = false;Record next = null;/*** 重置记录项*/public void init(int start) {this.start = start;}/*** 记录构成词的游标位置 仅标准词(词典存在的词)才会调用此方法*/public void addIndex(int cursor) {assert (maxIdx < MAX_NUM - 1) : "字符序列成词数目越界,扩大词数目.";end[++maxIdx] = cursor;}/*** 重置记录项*/public void reset() {continued = false;wordClass = WordClass.OTHER;for (int i = 0; i <= maxIdx; i++) {end[i] = 0;}maxIdx = -1;}}/*** 记录前移,交换角色*/private void moveRocord() {Record swap = last;last = curr;curr = swap;curr.reset();}/*** 判断当前字符序列是否在字典中构成一个完整的词** @return boolean 是否在字典中构成一个完整的词*/private boolean isStandardWord(char[] wordArr) {//代码略}/*** 判断当前字符在字符序列里是否是孤立字符(不能够成为中文词首)** @return boolean 是否是孤立字符*/private boolean isIsoLatedChar(char[] charArray, int cursor) {// 代码略}/*** 文本分词 正向最大匹配改进算法** @param text 输出待分词文本* @param separator 分隔符* @return 使用分隔符隔开的词文本*/private String forwardMaxMatch(String text, String separator) {assert SEG_CONG.segMethod.equals(SegAlgorithm.FORWARD) : "算法类型设置错误。";//代码略}/*** 根据条件增加分隔符** @param start 下一记录起始位置*/private void addSeparator(int start) {//如果还未分割if (curr.continued) {if (SEG_CONG.markNewWordFlag) {switch (curr.wordClass) {case NEW_WORD:splited.append(SegmentArgs.NEW_WORD_MARK);break;case CN_EN_MIX:splited.append(SegmentArgs.CN_EN_MIX_MARK);break;case SPLICE_WORD:splited.append(SegmentArgs.SPLICE_WORD_MARK);break;default:break;}}splited.append(SEG_CONG.separator);curr.addIndex(start);moveRocord();curr.init(start);}}/*** 处理(阿拉伯数字)数量词** @param charArray 字符序列* @param cursor 输入游标位置* @return boolean 是否完成*/private boolean handleQuantifier(char[] charArray, int cursor) {int start = cursor;char currChar = charArray[cursor];//正向最大匹配的数字前一个是未分割if (cursor > 0) {//考虑前一个字符Character prev = charArray[cursor - 1];if (!Unicode.isDecimal(prev) && !Unicode.isPoint(prev)) {addSeparator(start);}}//正向最大匹配的数字+量词if (cursor < charArray.length - 1) {//正向的考虑后一个字符Character next = charArray[++cursor];if (Unicode.isQuantifier(next)) {splited.append(currChar);splited.append(next);splited.append(SEG_CONG.separator);curr.continued = false;curr.wordClass = WordClass.QUANTIFIER;cursor++;curr.addIndex(cursor);moveRocord();return true;}}return false;}/*** 词典中查找匹配的词** @param charArray 字符序列* @param cursor 当前游标* @return boolean 是否搜索到*/private boolean searchInDictionary(char[] charArray, int cursor) {//代码略}/*** 处理中文数字** @param charArray 字符序列* @param cursor 输入游标位置* @return cursor 输出游标位置*/private int handleCNNumeral(char[] charArray, int cursor) {int start = cursor;char currChar = charArray[cursor];addSeparator(start);splited.append(currChar);cursor++;curr.wordClass = WordClass.QUANTIFIER;while (cursor < charArray.length) {currChar = charArray[cursor];if (Unicode.isNumeral(currChar)) {splited.append(currChar);cursor++;} else if (Unicode.isQuantifier(currChar)) {splited.append(currChar);cursor++;break;} else {break;}}splited.append(SEG_CONG.separator);curr.end[0] = cursor;curr.maxIdx = 0;moveRocord();return cursor;}/*** 处理中文孤立字符** @param charArray 字符序列* @param cursor 输入游标位置* @return int 输出游标位置*/private int handleIsoLatedCNChar(char[] charArray, int cursor) {// 代码略}/*** 文本分词 反向** @param text 输出待分词文本* @param separator 分隔符* @return 使用分隔符隔开的词文本*/private String reverseMaxMatch(String text, String separator) {assert SEG_CONG.segMethod.equals(SegAlgorithm.REVERSE) : "算法类型设置错误。";//代码略}/*** 获取 RobinSeg 分词类的实例** @return 分词类的单实例*/public static AbstractSegmenter getInstance() {if (null == instance) {instance = new RobinSeg();}return instance;}
}
4.4 运行结果
分词效果
-----------------------------分词效果-------------------------------
【-用例原始文本-】:马云,中国著名企业家,浙江绍兴人,阿里巴巴集团主要创始人之一。现任阿里巴巴集团主席和首席执行官,他是《福布斯》杂志创办50多年来成为封面人物的首位大陆企业家,曾获选为未来全球领袖。董事等职务。2013年3月11日,阿里巴巴集团董事局主席兼CEO马云昨日发出内部邮件称,集团首席数据官陆兆禧将接任CEO一职。
【拼接-分类-模式】:马云[⊙新词]|中国|著名|企业家|浙江|绍兴|人|阿里巴巴|集团|主要|创始人|之一|现任|阿里巴巴|集团|主席|和|首席执行官|他是|福布斯|杂志|创办|50|多年来|成为|封面人物|的|首位|大陆|企业家|曾|获选|为|未来|全球|领袖|董事|等|职务|2013年|3月|11日|阿里巴巴|集团|董事局|主席|兼|ceo马云[⊙混合词]|昨日|发出|内部|邮件|称|集团|首席|数据|官[⊙新词]|陆兆|禧|将|接任|ceo|一|职|
【拼接-检索-模式】:马云[⊙新词]|中|中国|著名|企业|企业家|浙江|绍兴|人|阿|阿里|阿里巴巴|巴巴|集团|主要|要|创始|创始人|人|之|之一|现任|任|阿|阿里|阿里巴巴|巴巴|集团|主席|和|首席|首席执行官|执行|执行官|他|他是|是|福布斯|杂志|创办|办|50|多|多年|多年来|年来|来|成|成为|为|封面|封面人物|面人|人|人物|的|首位|大|大陆|企业|企业家|曾|获选|选|选为|为|未来|来|全球|领|领袖|董事|等|职务|2013年|3月|11日|阿|阿里|阿里巴巴|巴巴|集团|董事|董事局|主席|兼|ceo马云[⊙混合词]|昨日|日|发|发出|出|内部|邮件|称|集团|首席|数|数据|据|官[⊙新词]|陆兆|禧|将|接|接任|任|ceo|一|职|
-------------------------------------------------------------------
【-用例原始文本-】:阿拉伯金额数字万位和元位是"0",或者数字中间连续有几个"0",万位、元位也是"0",但千位、角位不是"0"时,中文大写金额中可以只写一个零字,也可以不写"零"字。如¥1680.32,应写成人民币壹仟陆佰捌拾元零叁角贰分,或者写成人民币壹仟陆佰捌拾元叁角贰分,又如¥107000.53,应写成人民币壹拾万柒仟元零伍角叁分,或者写成人民币壹拾万零柒仟元伍角叁分。
【拼接-分类-模式】:阿拉伯|金额|数字|万位[⊙新词]|和|元位[⊙拼接词]|是|0|或者|数字|中间|连续|有几个|0|万位[⊙新词]|元位[⊙拼接词]|也是|0|但|千位[⊙新词]|角位[⊙拼接词]|不是|0|时|中文|大写|金额|中|可以|只写|一个|零字|也可以|不|写|零|字|如|1680.32|应|写成|人民币|壹仟|陆佰|捌拾元|零叁角|贰分|或者|写成|人民币|壹仟|陆佰|捌拾元|叁角|贰分|又如|107000.53|应|写成|人民币|壹拾万|柒仟|元|零伍角|叁分|或者|写成|人民币|壹拾万|零柒仟|元|伍角|叁分|
-------------------------------------------------------------------
【-用例原始文本-】:p非v IBM研究院 IBM非 VC维 VC银翘片,魅族MX系列。我很喜欢陈述高的演讲,我很不喜欢陈述高调的样子。人们向林俊德表示深切的问候。中华人民共和国
【拼接-分类-模式】:p非v[⊙混合词]|ibm|研究院|ibm非[⊙混合词]|vc维[⊙混合词]|vc银翘片[⊙混合词]|魅族mx[⊙混合词]|系列|我很|喜欢|陈述高[⊙拼接词]|的|演讲|我很|不喜欢|陈述|高调|的|样子|人们|向|林俊德[⊙新词]|表示|深切|的|问候|中华人民共和国|
-------------------------------------------------------------------
【-用例原始文本-】:姚明退役了。草泥马的,据路透社报道,印度尼西亚社会事务部一官员星期二(29日)表示,日惹市附近当地时间27日晨5时53分发生的里氏6.2级地震已经造成至少5427人死亡,20000余人受伤,近20万人无家可归。
【拆分-分类-模式】:姚明|退役|了|草泥马[⊙新词]|的|据|路透社|报道|印度尼西亚|社会|事务部|一|官员|星期二|29日|表示|日惹|市|附近|当地时间|27日|晨|5时|53分|发生|的|里氏|6.2级|地震|已经|造成|至少|5427|人|死亡|20000|余人|受伤|近|20万|人|无家可归|
【拼接-分类-模式】:姚明|退役|了|草泥马[⊙新词]|的|据|路透社|报道|印度尼西亚|社会|事务部|一|官员|星期二|29日|表示|日惹市[⊙拼接词]|附近|当地时间|27日|晨|5时|53分|发生|的|里氏|6.2级|地震|已经|造成|至少|5427|人|死亡|20000|余人|受伤|近|20万|人|无家可归|
-------------------------------------------------------------------
【-用例原始文本-】:歧义和同义词:研究生命起源,混合词: 做B超检查身体,本质是X射线,单位和全角: 2009年8月6日开始大学之旅,中文数字: 四分之三的人都交了六十五块钱班费,那是一九九八年前的事了,四川麻辣烫很好吃,五四运动留下的五四精神。笔记本五折包邮亏本大甩卖。人名识别: 我是陈鑫,也是jcesg的作者,三国时期的诸葛亮是个天才,我们一起给刘翔加油,罗志高兴奋极了因为老吴送了他一台笔记本。配对标点: 本次『畅想杯』黑客技术大赛的得主为电信09-2BF的张三,奖励C++程序设计语言一书和【畅想网络】的『PHP教程』一套。特殊字母: 【Ⅰ】(Ⅱ),英文数字: bug report chenxin619315@gmail.com or visit http://code.google.com/p/jcseg, 15% of the day's time i will be there.特殊数字: ① ⑩ ⑽ ㈩.
【拆分-分类-模式】:歧义|和|同义词|研究生|命|起源|混合|词|做|b超[⊙混合词]|检查|身体|本质|是|x|射线|单位|和|全角|2009年|8月|6日|开始|大学|之旅|中文数字|四分之三|的|人|都|交了|六十五块|钱|班费|那是|一九九八年|前|的|事|了|四川|麻辣烫|很好|吃|五四运动|留下|的|五四|精神|笔记本|五折|包|邮|亏本|大|甩卖|人名|识别|我是|陈鑫[⊙新词]|也是|jcesg|的|作者|三国|时期|的|诸葛亮[⊙新词]|是个|天才|我们|一起|给|刘翔[⊙新词]|加油|罗志[⊙新词]|高兴|奋|极了|因为|老吴|送了|他|一台|笔记本|配对|标点|本次|畅想|杯|黑客|技术|大赛|的|得主|为|电信|09|2bf|的|张三|奖励|c|程序设计语言|一书|和|畅想|网络|的|php|教程|一套|特殊|字母|英文|数字|bug|report|chenxin|619315|gmail|com|or|visit|http|code|google|com|p|jcseg|15%|of|the|day|s|time|i|will|be|there|特殊|数字|
【拼接-分类-模式】:歧义|和|同义词|研究|生命|起源|混合词[⊙拼接词]|做|b超[⊙混合词]|检查|身体|本质|是|x|射线|单位|和|全角|2009年|8月|6日|开始|大学|之旅|中文数字|四分之三|的|人|都|交了|六十五块|钱|班费|那是|一九九八年|前|的事[⊙拼接词]|了|四川|麻辣烫|很好|吃|五四运动|留下|的|五四|精神|笔记本|五折|包邮[⊙拼接词]|亏本|大|甩卖|人名|识别|我是|陈鑫[⊙新词]|也是|jcesg|的|作者|三国|时期|的|诸葛亮[⊙新词]|是个|天才|我们|一起|给|刘翔[⊙新词]|加油|罗志[⊙新词]|高兴奋[⊙拼接词]|极了|因为|老吴|送了|他|一台|笔记本|配对|标点|本次|畅想杯[⊙拼接词]|黑客|技术|大赛|的|得主|为|电信|09|2bf|的|张三|奖励|c|程序设计语言|一书|和|畅想|网络|的|php|教程|一套|特殊|字母|英文|数字|bug|report|chenxin|619315|gmail|com|or|visit|http|code|google|com|p|jcseg|15%|of|the|day|s|time|i|will|be|there|特殊|数字|
-------------------------------------------------------------------
【-用例原始文本-】: ENGLISH CHInese WhAt are you doING!. The state investigation that followed the AJC’s analyses of test scores depicted a culture that rewarded cheaters, punished whistle-blowers and covered up improprieties.
【拼接-分类-模式】:english|chinese|what|are|you|doing|the|state|investigation|that|followed|the|ajc|s|analyses|of|test|scores|depicted|a|culture|that|rewarded|cheaters|punished|whistle|blowers|and|covered|up|improprieties|
-------------------------------------------------------------------
【-用例原始文本-】:全角半角、大小写转换 小数:5条狗,4.5个 6.3 6.7 0.6 7.8 1.5 ENglIsH ChineSE. TExt.SEGMenT 0.1%2.3$4.5¥6.7%8.9¥ 11.2 %¥$
【拆分-分类-模式】:全角|半角|大小写|转换|小数|5条|狗|4.5个|6.3|6.7|0.6|7.8|1.5|english|chinese|text|segment|0.1%|2.3$|4.5¥|6.7%|8.9¥|11.2|
-------------------------------------------------------------------
分词性能
⊙字符总数:[ 17.25 ]W. 用时:[ 18 ]ms。 速度:[ 958W ]字符/秒。文件名:data/凯文凯利-失控.txt
失控|全人类|的|最终|命运|和|结局|作者|美|凯文[⊙新词]|凯利[⊙新词]|著|东西|文库|译|出版社|新星|出版社|出版|时间|2010|12|1|版次|1|页数|700|字数|500000|印刷|时间|2010|12|1|开本|16开|纸张|胶版纸|印次|1|isbn|9787513300711|包装|平装|内容简介|这是|黑客帝国|主要|演员|的|必读物[⊙拼接词]|之一|这本|关于|
-------------------------------------------------------------------
⊙字符总数:[ 37.10 ]W. 用时:[ 34 ]ms。 速度:[ 1091W ]字符/秒。文件名:data/绝影-疯狂的程序员.txt
疯狂|的|程序员|绝影[⊙新词]|1|hello|world|天|已经|七分|黑了|屋里|却|还没|开灯|这个|全身|黑衣服|的|男子|突然|像|想起|什么|从|包里[⊙拼接词]|掏出烟[⊙拼接词]|抽出|一只|递给|旁边|的|人|兄弟|抽烟|么|那烟[⊙拼接词]|是|红塔山|旁边|那人|连忙|一边|摆手|一边|说|不|不|语气|有点|紧张|好像|那|黑衣服|递过来|的|不是烟[⊙拼接词]|是|海
-------------------------------------------------------------------
⊙字符总数:[ 4.27 ]W. 用时:[ 5 ]ms。 速度:[ 853W ]字符/秒。文件名:data/高晓松-如丧.txt
如丧[⊙拼接词]|我们|终于|老得|可以|谈谈|未来|序|时隔|十二年|为|出版|第二|本|文集|坐在|洛杉矶|垂垂[⊙新词]|夕阳|下|校对|文稿|看到|歌词|部分|时|忽然|瞥见|好多年|前|给|叶蓓|的|几句词[⊙拼接词]|夕阳|你|温暖|的|肩膀|我|柔软的|心房|大地|以及|忧伤|每一|天|在|我心|上|我为你舞[⊙拼接词]|在|远方|我是|你的|花|我不|管|春天|有多|长|正好在|夕
-------------------------------------------------------------------
⊙字符总数:[ 235.73 ]W. 用时:[ 238 ]ms。 速度:[ 990W ]字符/秒。文件名:data/谭松波-体育-2805P.txt
1|跳水队[⊙拼接词]|老大哥|熊倪[⊙新词]|在|一个|集体|跳水|的|动作|中|因|队友|失手|不|配合|头撼[⊙新词]|对方|的|臀部|而|伤|及|後颈[⊙新词]|香港电[⊙拼接词]|高台|集体|跳水|失手|奥运|巨星|熊倪[⊙新词]|伤颈[⊙拼接词]|万众瞩目|的|中国|跳水队[⊙拼接词]|昨天|首次|在|九龙|公园|表演|时|险|生|悲剧|跳水队[⊙拼接词]|老大哥|熊倪[⊙新词]|在|
-------------------------------------------------------------------
⊙字符总数:[ 14.01 ]W. 用时:[ 14 ]ms。 速度:[ 1001W ]字符/秒。文件名:data/塞林格-麦田里的守望者.txt
麦田|里的|守望|者|作者|塞林格[⊙新词]|状态|全本|内容简介|本书|的|主人公|霍尔顿[⊙拼接词]|是个|中学生|出身|于|富裕|的|中产阶级|家庭|他|虽|只有|16岁[⊙新词]|但|比|常人|高出|一头|整日|穿着|风雨衣|戴着|鸭舌帽|游游荡荡|不愿|读书|他对|学校|里的|一切|老师|同学|功课|球赛|等等|全都|腻烦|透了|3次[⊙新词]|被|学校|开除|又一个|学期结束|了|他|
-------------------------------------------------------------------
5 对比验证
本文通过与其它前述几种分词器对比验证分类效果。
5.1 分词速度对比
实测环境说明
(1)测试样本
样本分类 | 名称 | 字符数(万) |
---|---|---|
电子书 | 塞林格-《麦田里的守望者》 | 14 |
绝影-《疯狂的程序员》 | 37 | |
凯文凯利-《失控——全人类的最终命运和结局》 | 49 | |
高晓松-《如丧》片段 | 4.3 | |
网页语料 | 2805篇体育类新闻 | 236 |
819篇财经类新闻 | 148 | |
1040篇科技类新闻 | 108 | |
2943篇电脑类新闻 | 238 |
样本分成8个字符串序列,字数总计834万,字节大小 15.91 MB(按照java字符内码占两个字节估计).
(2)测试说明
每一种分类器都将上述样本分三次求得平均分词速度,分词速度统计都不包括文本加载时间。各分类器预先都进行短文本分词预热,避免首次加载词典等初始化操作造成的时间误差。所有分词算法都采用单线程测试。
(3)测试机
机器 | CPU | OS |
---|---|---|
服务器 | Xeon E5-2670 2.6GHz | Ubuntu 14.04.5 LTS |
PC | Core i5-3210 2.5GHz | Windows 7 |
服务器运行输出结果如下:
PC机运行输出结果如下:
分词速度对比如图所示:
5.2 分词结果对比
两段短文本在各分词器上的分词效果如下所示:
--------------------------------------------------------------------------------------------------------------------------------
原始文本:时隔十二年,为出版第二本文集,坐在洛杉矶垂垂夕阳下校对文稿,看到歌词部分时忽然瞥见好多年前给叶蓓的几句词。
--------------------------------------------------------------------------------------------------------------------------------
[RS]分词:时隔|十二年|为|出版|第二|本|文集|坐在|洛杉矶|垂垂|夕阳|下|校对|文稿|看到|歌词|部分|时|忽然|瞥见|好多年|前|给|叶蓓|的|几句词|
[IK]分词:时隔|十二年|年|为|出版|第二|第|二|本文|本|文集|坐在|洛杉矶|垂|垂|夕阳|下|校对|对文|文稿|看到|歌词|部分|分时|忽然|瞥见|见好|好多年|多年前|多|年前|年|给|叶蓓|的|几句|几|句词|句|
[JE]分词:时隔|十二年|出版|第二本|文集|坐在|洛杉矶|垂|垂|夕阳|校对|文稿|看到|歌词部|分时|忽然|瞥见|好多|年前|给|叶蓓|几|句词|
[MS]分词:时隔|十二|年|为|出版|第二|本|文集|坐在|洛杉矶|垂|垂|夕阳|下|校对|文稿|看到|歌词|部分|时|忽然|瞥见|好多|年前|给|叶|蓓|的|几句|词|
[PD]分词:时|隔|十|年|二年|出|版|第|第二|本|文|文集|坐|坐在|洛杉矶|垂垂|夕阳|阳下|对|校对|文|文稿|看到|歌词|部|分|时|忽然|瞥见|见好|多|好多|年|前|叶蓓|句|几句|句词|
[SS]分词:时隔|十|二年|为|出版|第二|本|文集|坐在|洛杉矶|垂垂|夕阳|下|校对|文稿|看到|歌词|部|分时|忽然|瞥见|好多|年前|给|叶蓓|的|几|句词|
--------------------------------------------------------------------------------------------------------------------------------
原始文本:据路透社报道,印度尼西亚社会事务部一官员星期二(29日)表示,日惹市附近当地时间27日晨5时53分发生的里氏6.2级地震已经造成至少5427人死亡,20000余人受伤,近20万人无家可归。
--------------------------------------------------------------------------------------------------------------------------------
[RS]分词:据|路透社|报道|印度尼西亚|社会|事务部|一|官员|星期二|29日|表示|日惹市|附近|当地时间|27日|晨|5时|53分|发生|的|里氏|6.2级|地震|已经|造成|至少|5427|人|死亡|20000|余人|受伤|近|20万|人|无家可归|
[IK]分词:据|路透社|路|报道|印度尼西亚|社会事务|事务部|一|官员|星期二|二|29|日|表示|日|惹|市|附近|当地时间|27|日|晨|5|时|53|分发|分|发生|的|里氏|6.2|级|地震|已经|造成|至少|5427|人|死亡|20000|余人|余|人|受伤|近|20|万人|万|人|无家可归|
[JE]分词:据|路透社|报道|印度尼西亚|社会|事务部|官员|星期二|29日|表示|日惹市|附近|当地时间|27日|晨|5时|53分发|生的|里氏|6.2级|地震|已经|造成|至少|5427人|死亡|20000|余人|受伤|近|20万人|无家可归|
[MS]分词:据|路透社|报道|印度尼西亚|社会事务|部|一|官员|星期二|29|日|表示|日|惹|市|附近|当地时间|27|日|晨|5|时|53|分发|生的|里|氏|6|2|级|地震|已经|造成|至少|5427|人|死亡|20000|余|人|受伤|近|20|万人|无家可归|
[PD]分词:路透社|道|报道|印度|印度尼西|西亚|会|社会|事|事务|部|1|官员|星期|星期二|29|日|表示|日|日惹|日惹市|近|附近|地|时|间|当地时间|27|日|晨|5|时|53|分|发|生|生的|里氏|6.2|级|地|地震|经|已经|造|成|至少|5427|人|死|死亡|20000|余人|受|伤|近|200000|人|家|归|无家可归|
[SS]分词:据|路透社|报道|印度尼西亚|社会|事务部|一|官员|星期二|29|日|表示|日惹|市|附近|当地时间|27|日|晨|5|时|53|分发|生的|里氏|6.2|级|地震|已经|造成|至少|5427|人|死亡|20000|余人|受伤|近|20|万|人|无家可归|
下图红色底色标示的分词结果“明显错误”,灰色的“具有争议”,可以看出知更鸟分词器(RS)分词有非常好的准确度。
6 总结
通过上述实测结果可以看出知更鸟分词器具有良好的性能:
- 高精度:通过各种分词器对比,看出RS分词准确度较高;
- 高效率:单线程分词速度千万字符/秒(量级),字节处理速度15MB/s;
- 模式多样:支持多种分词模式,有效支持中文文本分类等自然语言处理应用。
知更鸟博文推荐 | |
---|---|
上一篇 | 自然语言处理——文本分类概述 |
下一篇 | 文本分类——特征选择概述 |
推荐篇 | 基于Kubernetes、Docker的机器学习微服务系统设计——完整版 |
研究篇 | RS中文分词 | MP特征选择 | NLV文本分类 | 快速kNN |
作者简介 | |
兴趣爱好 | 机器学习、云计算、自然语言处理、文本分类、深度学习 |
xsd-jj@163.com (欢迎交流) |
参考:
[1]https://blog.csdn.net/u013063153/article/details/72904322
[2]http://blog.jobbole.com/111680/
[3]http://blog.51cto.com/tianxingzhe/1720067
[4]https://blog.csdn.net/flysky1991/article/details/73948971
版权声明:个人原创,请勿抄袭,欢迎引用,未经许可禁止转载. © 知更鸟
中文分词——知更鸟分词(RS)设计与实现相关推荐
- 自然语言处理系列十七》中文分词》分词工具实战》Python的Jieba分词
注:此文章内容均节选自充电了么创始人,CEO兼CTO陈敬雷老师的新书<分布式机器学习实战>(人工智能科学与技术丛书)[陈敬雷编著][清华大学出版社] 文章目录 自然语言处理系列十七 分词工 ...
- 中文开源汉语分词工具
本文转载自:http://www.scholat.com/vpost.html?pid=4477 由于中文文本词与词之间没有像英文那样有空格分隔,因此很多时候中文文本操作都涉及切词,这里整理了一些中文 ...
- Rstudio 实现 爬虫 文本分词 个性化词云设计--我爱中国我爱党
Rstudio 爬虫 文本分词个性化词云设计 目录 1.环境准备,加载依赖 2.rvest 爬虫,数据爬取 3.jiebaR用于分词,词频统计 4.wordcloud2 结果可视化 ========= ...
- pyhanlp 中文词性标注与分词简介
pyhanlp 中文词性标注与分词简介 pyhanlp实现的分词器有很多,同时pyhanlp获取hanlp中分词器也有两种方式 第一种是直接从封装好的hanlp类中获取,这种获取方式一共可以获取五种分 ...
- 中文分词器分词效果的评测方法
[原创]中文分词器分词效果的评测方法 2013年8月27日 由 learnhard留言 » 转载请注明出处:http://www.codelast.com/ 现在有很多开源的中文分词器库,如果你的项目 ...
- solr配置中文IK Analyzer分词器
1.下载IK Analyzer分词器文件 链接: https://pan.baidu.com/s/1hrA1YyK 密码: 9hpk 中文IK Analyzer分词器的相关配置使用资料: 链接:htt ...
- es拼音分词 大帅哥_SpringBoot集成Elasticsearch 进阶,实现中文、拼音分词,繁简体转换...
Elasticsearch 分词 分词分为读时分词和写时分词. 读时分词发生在用户查询时,ES 会即时地对用户输入的关键词进行分词,分词结果只存在内存中,当查询结束时,分词结果也会随即消失.而写时分词 ...
- 公司开源的java分词,Java开源项目cws_evaluation:中文分词器分词效果评估
通过对前文<word分词器.ansj分词器.mmseg4j分词器.ik-analyzer分词器分词效果评估>中写的评估程序进行重构改进,形成了一个新的Java开源项目cws_evaluat ...
- 处理中文分词 ik分词器以及拓展和停止字典
一. 处理中文分词 以及 ik分词器的应用 解决: 1. 在es-plugins中添加安装 ik分词器 IK分词器包含两种模式: ik_smart:最少切分 ik_max_word:最细切分 2. 容 ...
最新文章
- 计算机删除百度云盘图标,win10系统百度云盘图标删除的操作方法
- html-head-body
- Prompt-based Language Models:模版增强语言模型小结
- Web前端培训:有哪些好用的前端开发工具呢?
- 爬虫之操作excel
- python delete_rows,Python:如何刪除以特定字符結尾的行?
- 男朋友就是要这个样子的
- XDUOJ 1125 Judgement of Orz Pandas
- SI4463软件开发记录
- BlackBerry 7290如何传自定义图片
- CIO峰会:企业私有云存储实践方案
- 向上滚动的文字的淡入淡出效果
- 贝叶斯分类器,什么是朴素贝叶斯,后续为使用贝叶斯实现海量数据的邮件筛选。带源码数据集和解决思路
- Python silk 库 支持微信语音
- 前后端分离,SpringBoot如何实现验证码操作
- Attributed Graph Clustering: A Deep Attentional Embedding Approach,IJCAI2019
- matlab把图片制作成视频
- 周周周报报报(药店管理系统)
- kali linux 命令
- 如何选择CDN?你需要关注这三个方面