基于.NET的分词软件设计与实现V2.0--性能问题说明及功能增强
之前发了基于.NET的分词软件设计与实现V1.0--总体思路及算法实现,发现园子里面还是有挺多关注的,有人跟我消息说想让搞成一个本科毕业论文设计的形式,录成视频,偶这个菜菜表示有点忐忑,这个还在商量中,所以为了留点小悬念,偶不再放出类的完成代码(当然,您是大牛的话肯定不需要的)。
首先说明下很多人留言中提到的性能问题,这肯定是这个软件在设计时的重中之重,所以我肯定会详细考虑,之所以这个系列计划写10+篇,也是因为偶在性能方面作了很多测试,所以性能问题大家不必担心,我在自己能力所及的范围内对性能作了最大化的提升,最后的性能也希望能让大家满意。
好了,废话已尽,来正题吧。。。
首先来看V1.0存在的问题及V2.0的改进方案:
1、 V1.0存在的问题:没有性能测试功能
V2.0的改进方案:增加分词时间测试功能(使用了Stopwatch)
理由:不说了。。^_^
2、 V1.0存在的问题:词典收录的词汇较少
V2.0的改进方案:通过扩充词库增加分词的准确度
理由:首先举个简单的例子,为什么有这么多的输入法,但搜狗输入法能成为所谓的“装机必备”软件,很显然,因为大家觉得好用,但又问什么好用呢,抛开一些人性化的设计不说,根源其实就在其拥有海量的搜狗词库,貌似总共有1G多,而且每天大家还可以看到更新的新鲜词汇,这样大家在输入的时候能够很轻松的在第一页甚至是第一个选项中找到自己想要的词汇,甚至你打词的拼音首字母,甚至很长的一句话,都能准确的匹配到你想要的。
可见,词典收录的词汇的多少,直接影响到分词的准确度,所以扩充词库可以提高分词的正确率。在个人V1.0版中,收录的词典有1.2M的样子,而在V2.0版中,在网上下到了一个更全的词库,感兴趣的可以猛击这里下载。
3、 V1.0存在的问题:文本缺乏预处理
V2.0的改进方案:在分词之前利用正则匹配对文本进行预处理,去除一个或多个空白字符、换行符等
理由:想象一段文本,如果某人使坏,故意在比如“中国”之间加入多个空白符或者换行符,由于我们是通过正则表达式,通过标点进行断句的方法进行操作,所以这势必会对最后的结果造成影响,效果如下:
基于上述原因,我们有必要在分词之前对文本进行预处理。
4、 V1.0存在的问题:无法对英文、数字及特殊符号进行分词
V2.0的改进方案:分离“标点符号词典”,分别构建匹配中文和非中文的正则表达式,增加对英文、数字及特殊符号的分词功能
首先,我们来看一下1.0版在增加英文和数字分词时的效果:
可以看到分词的结果异常凄惨,原因就在于我们对于英文和中文标点“一视同仁”,并且英文单词显然不会在中文的词典中存在,所以进行逆向最大匹配算法匹配时,会一直无法匹配成功,而最后均以单子的形式被划分,最后输出。
所以我在V2.0中提出了分离标点符号词典的方案,即将中英文的标点符号拆分开来,分别构造正则表达式,我们在断句时以中文标点为标识进行断句,而对英文标点不作特殊处理,这样就成功解决了对于英文、数字及特殊符号的分离,诸如:1.4,#1,¥111,12.3%,xx@163.com等等。
代码更新如下:
1 // 字段更新
2 /// <summary>
3 /// updated:中文标点分隔符
4 /// </summary>
5 string _chineseSpiltters;
6 /// <summary>
7 /// updated:英文标点分隔符
8 /// </summary>
9 string _englishSpiltters;
10
11 //构造函数更新
12 public Splitter(string inputStr)
13 {
14 //updated:
15 this._inputStr = PreProcess(inputStr);
16 //updated:
17 _dict = GetVocabularyDictionary("Vocabulary.txt");
18 _chineseSpiltters = GetPunctuationDictionary("ChinesePunctuations.txt");
19 _englishSpiltters = GetPunctuationDictionary("EnglishPunctuations.txt");
20 }
21
22 //方法更新
23 /// <summary>
24 /// 对待分词文本进行预处理(如删除一个或多个标点符号、空白字符、换行符等)
25 /// </summary>
26 /// <param name="str">待分词文本</param>
27 static string PreProcess(string str)
28 {
29 //updated
30 Regex regex = new Regex("[ \r\n ]+");
31 if (regex.IsMatch(str))
32 {
33 str = regex.Replace(str, "");
34 }
35 return str.Trim();
36 }
37
38 /// <summary>
39 /// 获得字符串中匹配的标点符号的集合(去除重复项)
40 /// </summary>
41 List<string> GetMatchedSpiltters()
42 {
43 //updated:
44 //使用+匹配,可匹配一个或多个连续的标点符号,如。。。
45 Regex regex = new Regex("[" + _chineseSpiltters + "]+");
46 return GetMatchedContent(regex);
47 }
48
49 /// <summary>
50 /// Updated:得到所有不是中文的字符集合
51 /// </summary>
52 public List<string> GetNonChinese()
53 {
54 Regex regex = new Regex("[" + _englishSpiltters + "0-9A-Za-z]+");
55 return GetMatchedContent(regex);
56 }
详细类设计图如下:
程序流程图(示例句子纯属虚构):
测试:
很吓人的数字吧。。呵呵。。没事。。精彩待续。。^_^
出处:http://www.cnblogs.com/RockyMyx/
本文版权归作者和博客园共有,欢迎转载,但请在文章明显位置给出原文连接,否则保留追究法律责任的权利。