NLP中文信息处理---正向最大匹配法分词

弄了好几天正向最大匹配法分词,终于弄完了吧。Python写的。Python确实是一门好语言,写起来很简单、顺手。


一、关于正向最大匹配法分词

中文分词(Chinese Word Segmentation)指的是将一个汉字序列切分成一个一个单独的词。中文分词是文本挖掘的基础,对于输入的一段中文,成功的进行中文分词,可以达到电脑自动识别语句含义的效果。


正向最大匹配法

例子: 将句子 ’ 今天来了许多新同事 分词。  最大词长为5

今天来了许
今天来了
今天来
今天  ====》 得到一个词 – 今天
来了许多新
来了许多
来了许
来了
来   ====》 得到一个词 –
了许多新同
了许多新
了许多
了许
了   ====》 得到一个词 –
许多新同事
许多新同
许多新
许多 ====》得到一个词 – 许多
新同事
新同
新   ====》得到一个词 –
同事 ====》得到一个词 – 同事


最后正向最大匹配的结果是:/今天/来/了/许多/新/同事/


二、正向最大匹配分词算法



三、语料库的处理算法的输入


语料库的处理流程


输入:人民日报语料库199801.txt

输出:dict.txt词表文件


分词算法

输入:将dict.txt处理后得到的list集,以及最大词长;待分词的句子

输出:分词后的句子


四、Python实现

1. 语料库的初步处理 ( MaxBuildDict.py )

# -*- coding: cp936 -*-
#最大匹配法进行分词----创建词表文件.
#author 徐能
#date 2013/3/23
import string
import re

#输入:语料库199801.txt文件; 输出:换行分割后的词表文件dict.txt(已经去重复, 去日期)
def create_dict(filename):
	print("读取文件......")
	src_data = open(filename,'r').read()
	sp_data = src_data.split()#分割

	print("原始词数为:",len(sp_data))
	set_data = set(sp_data)	#去重复
	data = list(set_data) #set转换成list, 否则不能索引
	print("去除重复后总词数为:",len(data))

	print("正在建立词表文件......")
	tmp = []
	for i in range(0,len(data)):
		if re.compile(r'\d+\-\S+').match(data[i]):  #去除类似这样的词'19980101-01-001-002/m'
			continue
		else:
			p_ok_data = re.compile(r'\/\w+').sub('\n',data[i]) #将类似的词'埃特纳/ns'替换为'埃特纳'
			if re.compile(r'(\[\S+)|(\]\S+)').match(p_ok_data):    #找到以'['或']'开头的词
				ok_data = re.compile(r'(\]\w+\[)|(\])|(\[)').sub('',p_ok_data) #去除']nt[澳门',']澳门','[澳门'三类词的头部无用部分(先匹配长的部分)
				tmp.append(ok_data)
				continue

			tmp.append(p_ok_data)


	print("最终得到的词表文件中总词数为:",len(tmp))
	open('dict_tmp.txt','w').writelines(tmp)
	print("初步词表文件建立完成! (dict_tmp.txt)")


#运行
if __name__ == '__main__':
    create_dict('199801.txt')


2. 进一步对词表的优化 ( MaxBuildDictModify.py )

# -*- coding: cp936 -*-
#修正词表文件.
#author 徐能
#date 2013/3/24
import string
import re

#输入:dict_tmp.txt文件; 输出:dict.txt(已经去重复, 去特殊符号)
def create_dict(filename):
	print("读取文件......")
	src_data = open(filename,'r').read()
	data = src_data.split()#分割

	print("正在建立词表文件......")
	tmp = []
	for i in range(0,len(data)):
	   ok_data = re.compile(r'\]..').sub('',data[i]) #将类似的词']..埃特纳'前面的东西去掉
	   tmp.append(ok_data+'\n')

	print("去重复前的词数为:",len(tmp))
	set_data = set(tmp)	#去重复
	lalst_data = list(set_data) #set转换成list, 否则不能索引
	print("去除重复后总词数为:",len(lalst_data))

	open('dict.txt','w').writelines(lalst_data)
	print("最终词表文件建立完成! (dict.txt)")


#运行
if __name__ == '__main__':
    create_dict('dict_tmp.txt')
##    create_dict('testdict1.txt')
##    create_dict('testdict2.txt')


3. 分词算法实现 ( MaxWordSegmentation.py )

# -*- coding: cp936 -*-
#最大匹配法进行分词, 测试文件为MaxWordSegmentationTest.py
#author 徐能
#date 2013/3/25
import string
import re

#读入词表文件到内存list
#输入:词典文件名, 输出:词典中所有词的list表,其中最大词长
def load_dict(filename):
	f = open(filename,'r').read()
	maxLen = 1
	strList=f.split("\n")

	#寻找最大词长
	for i in strList:
		if len(i)>maxLen:
			maxLen=len(i)

	return strList,maxLen;

#分词方法.
#输入:词表中所有词的列表与其中的最大词长, 输出:分词后的列表
def segmentation(strList,maxLen,sentence):
	wordList=[]	 #用于输出的词列表

	while(len(sentence)>0):
		word=sentence[0:maxLen] #每次取最大词长的词

		meet=False;   #标记位, 判断是否找到该词

		while((not meet) and (len(word)>0)):
			#如果词在词表中
			if(word in strList):
				wordList.append(word)   #添加到输出列表
				sentence=sentence[len(word):len(sentence)]#后移
				meet=True;
			#词不在词表中时
			else:
				#当词长为1时, 添加到输出表, 并后移总词位
				if(len(word)==1):
					wordList.append(word)
					sentence=sentence[len(word):len(sentence)]
					meet=True;
				else:
				#当词长不为1时, 词长减1(最后一位)
					word=word[0:len(word)-1]
	return wordList

#主函数
def main():
	strList,maxLen=load_dict('dict.txt')
	print("词表中最大词长度为:",maxLen)
    #输入句子
	sentence = input('请输入中文句子:')
	print('输入的句子为:',sentence)
#	sentence='迈向充满希望的新世纪'
	print('输入的句子为:',sentence)
	length=len(sentence)
	print('输入的句子长度:',length)
	print("****************开始解析**********************")
	wordl=segmentation(strList,maxLen,sentence)
	#打印分词结果
	for eachChar in wordl:
		print(eachChar,end = "/ ")
	print("")#换行
	print("****************解析完毕!*********************")

#运行
if __name__ == '__main__':
	main()
五、运行结果





六、总结

关于效率:

正向最大匹配法分词占用很大计算量,结果本人测试,100多个字的一段话一般2秒分完。1000个字的一段话,需要20几秒才能分完。以最大词长为20来计算的话,待分的句子为20个字,假设全部分成2字词,词表中有5万个词,则计算量约为22*5*50000=550万。如此可见,当待分词句子很长,最大词长很大时,计算量是惊人的。

关于分词准确度:

正向最大匹配法的缺陷在与精确度不能达到理想的状态。同时也不能解决词的歧义问题。(统计结果表明,单纯使用正向最大匹配的错误率为1/169,单纯使用逆向最大匹配的错误率为1/245。


(文章如有错误,敬请指正)


运行源码以及全部文档下载地址: http://download.csdn.net/detail/xn4545945/5182311


原创文章,转载请注明出处:http://blog.csdn.net/xn4545945





你可能感兴趣的:(NLP/编译/Python)