中文分词 《第七篇》
一、分词的方法
分词的方法主要有以下几种:
1、单字切分
单字切分就是把一段文字按照每个字去建立索引。
如果用来切分“我爱你伟大的中国”,就会切成“我”,“爱”,“你”,“伟”,“大”,“的”,“中”,“国”。这种分词效率低,但也能解决一些问题,聊胜于无。
2、二分法
二分法就是把一段文字的每两个相邻的字算作一个词。同样对于上面的句子就会切成“我爱”,“爱你”,“你伟”,“伟大”,“大的”,“的中”,“中国”7个词。
3、词典法
词典法就是建立一个词典文件,然后使用词典和文字段落进行匹配,从而得出分词结果。在这种分词方法中,词典和匹配算法是关键。
做词典很容易,维护词典也不能,统计而已。
匹配算法不好办,有最大匹配和最小匹配,正向匹配和逆向匹配。二二得四,就成了“最大正向匹配”,“最大逆向匹配”,“最小正向匹配”和“最小逆向匹配”。
这四种分次发哪种最好没有定论,要根据具体文本段落而定。
4、语义法
这个方法在理论上是存在的,但从实际上讲也只是个名词。看到任何一段文字,让计算机将其正确理解出来,这个想法几乎不可能。即使是人也很难全部理解。
二、盘古分词
在.Net环境中,分词比较常用的是盘古分词,项目地址是:http://pangusegment.codeplex.com/
盘古分词词库下载地址是:http://pangusegment.codeplex.com/releases/view/47411
下载解压后如下:
- Demo.exe是分词的示例程序,用于测试分词效果。
- DictManage.exe用于词库管理。
分词测试效果就不说了,下面用一张图片来说明,如何对词库进行管理。
1、盘古分词初始设置说明
1、配置选项
盘古分词在初始化的时候,需要首先配置一些参数,这些参数可以通过MatchOptions类由代码设定,然后通过一些支持该类对象的构造方法来动态设置。
ICollection<WordInfo> words= segment.DoSegment(text); ICollection<WordInfo> words= segment.DoSegment(text, options); ICollection<WordInfo> words= segment.DoSegment(text, options, parameters);
- text 为需要分词的文本
- options 为自定义分词选项,默认为 pangu.xml 中指定的分词选项
- parameters 为分词参数,默认为 pangu.xml 中指定的分词参数
配置项列表如下:
MatchOptions属性 | 说明 |
ChineseNameIdentify | 是否开启中文人名识别 |
FrequencyFirst | 词频优先 |
MultiDimensionality | 是否开启多元分词 |
EnglishMultiDimensionality | 英文多元分词,这个开关,会将英文中的字母和数字分开 |
FilterStopWords | 是否过滤停用词 |
IgnoreSpace | 是否忽略空格、回车、Tab |
ForceSingleWord | 是否强制一元分词 |
TraditionalChineseEnabled | 是否开启繁体中文分词 |
OutputSimplifiedTraditional | 是否同时输出简体和繁体 |
UnknownWordIdentify | 是否开启未登录词别 |
FilterEnglish | 是否过滤英文,这个选项只有在过滤停用词选项生效时才有效 |
FilterNumeric | 是否过滤数字,这个选项只有在过滤停用词选项生效时才有效 |
IgnoreCapital | 是否忽略英文大小写 |
EnglishSegment | 英文分词 |
SynonymOutput | 同义词输出功能一般用于对搜索字符串的分词,不建议在索引时使用 |
WildcardOutput | 同义词输出功能一般用于对搜索字符串的分词,不建议在索引时使用 |
WildcardSegment | 对通配符匹配的结果分词 |
CustomRule | 是否进行用户自定义规则匹配 |
2、配置参数
配置参数通过MatchParameter类设定,在xml里设定也可以:
MatchParameter属性 | 说明 |
Redundancy | 多元分词冗余度 |
UnknowRank | 未登录词权值 |
BestRank | 最匹配词权值 |
SecRank | 次匹配词权值 |
ThirdRank | 再次匹配词权值 |
SingleRank | 强行输出的单字的权值 |
NumericRank | 数字的权值 |
EnglishRank | 英文词汇权值 |
SymbolRank | 符号的权值 |
SimplifiedTraditionalRank | 强制同时输出简繁汉字时,非原来文本的汉字输出权值。原来文本是简体,这里就是输出的繁体字的权值,反之亦然 |
SynonymRank | 同义词权值 |
WildcardRank | 通配符匹配结果的权值 |
FilterEnglishLength | 过滤英文选项生效时,过滤大于这个长度的英文 |
FilterNumericLength | 过滤数字选项生效时,过滤大于这个长度的数字 |
CustomRuleAssemblyFileName | 用户自定义规则的配件文件名 |
CustomRuleFullClassName | 用户自定义规则的类的完整名,即带名字空间的名称 |
默认的PanGu.xml示例如下:
<?xml version="1.0" encoding="utf-8"?> <PanGuSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.codeplex.com/pangusegment"> <DictionaryPath>..\Dictionaries</DictionaryPath> <MatchOptions> <ChineseNameIdentify>true</ChineseNameIdentify> <FrequencyFirst>false</FrequencyFirst> <MultiDimensionality>false</MultiDimensionality> <FilterStopWords>true</FilterStopWords> <IgnoreSpace>true</IgnoreSpace> <ForceSingleWord>false</ForceSingleWord> <TraditionalChineseEnabled>false</TraditionalChineseEnabled> <OutputSimplifiedTraditional>false</OutputSimplifiedTraditional> </MatchOptions> <Parameters> <UnknowRank>1</UnknowRank> <BestRank>5</BestRank> <SecRank>3</SecRank> <ThirdRank>2</ThirdRank> <SingleRank>1</SingleRank> <NumericRank>1</NumericRank> <EnglishRank>5</EnglishRank> <SymbolRank>1</SymbolRank> <SimplifiedTraditionalRank>1</SimplifiedTraditionalRank> <Redundancy>0</Redundancy> </Parameters> </PanGuSettings>
配置项与上面两个类的属性一一对应。
2、查看分词示例
下面,先写个小Demo看看如何分词:
PanGu.Segment.Init(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/PanGu.xml"); Segment segment = new Segment(); ICollection<WordInfo> words = segment.DoSegment("张飞武功很好"); foreach (WordInfo w in words) { Console.WriteLine(w.Word); }
分词效果如下:
4、整合Lucene.net进行索引、搜索示例
下面是一个简单的示例:
static void Main(string[] args) { PanGu.Segment.Init(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/PanGu.xml"); //写入数据到索引 Analyzer analyzer = new PanGuAnalyzer(); Directory directory = new RAMDirectory(); IndexWriter.MaxFieldLength maxFieldLength = new IndexWriter.MaxFieldLength(10000); using (IndexWriter writer = new IndexWriter(directory, analyzer, maxFieldLength)) { Document document1 = new Document(); document1.Add(new Field("Sentence", "张三是一个牛人", Field.Store.YES, Field.Index.ANALYZED)); writer.AddDocument(document1); } //查找 using (IndexSearcher searcher = new IndexSearcher(directory)) { PanGuTokenizer ktTokenizer = new PanGuTokenizer(); ICollection<WordInfo> words = ktTokenizer.SegmentToWordInfos("一个"); StringBuilder result = new StringBuilder(); foreach(WordInfo word in words) { if (word == null) { continue; } result.AppendFormat("{0}^{1}.0", word.Word,(int)Math.Pow(3,word.Rank)); } QueryParser queryParser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, "Sentence", new PanGuAnalyzer(true)); Query query = queryParser.Parse(result.ToString()); TopDocs docs = searcher.Search(query, null, 1000); Document doc = searcher.Doc(docs.ScoreDocs[0].Doc); Console.WriteLine(doc.Get("Sentence")); } Console.ReadKey(); }
5、盘古分词高亮组件
直接上示例:
//创建HTMLFormatter,参数为高亮单词的前后缀 PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>"); //创建Highlighter ,输入HTMLFormatter 和盘古分词对象Semgent PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new Segment()); //设置每个摘要段的字符数 highlighter.FragmentSize = 50; //获取最匹配的摘要段 string ContentLighter = highlighter.GetBestFragment("一个", "张三是一个牛人"); Console.WriteLine(ContentLighter);
输出如下: