无监督识别词语算法的Python实现

我是创始人李岩:很抱歉!给自己产品做个广告,点击进来看看。  

无监督识别词语算法的Python实现

作者:邓旭东HIT

前几天写了《 简单的中文分词算法 》,今天就用Python写个 伪分词算法实现。

说 伪分词是因为我这脚本其实并不能对文本进行分词,只是计算两个汉字组合成词的概率(由于是无监督,前期没有人工介入,识别词的能力大大降低。)。 比如 ‘中’、’过’、’国’三个字的组成的字对有

‘中过’、’中国’、’过国’、’国过’、’国中’、’过中’,这六个 字对中,很容易就看到只有 中国这个 字对是能成词,其余都不是词。但是如果给你100个、1000个字,你怎么知道其中的能成词的字对呢。所以这里就要用统计学,统计语料中各个字对的概率,一般概率大者的 字对 有很大可能性是一个词。

代码实现

一、初始化

					
						import
						reclass
						Bayes
						(
						object
						):
						def
						__init__
						(
						self
						,
						corpus
						):
						
							#将语料只保留中文字符
							self._corpus = ''.join(re.findall(r'[\u4E00-\u9FD5]+',corpus))        #语料文本长度
							self._corpusLen = len(self._corpus)        #将语料切分为单字列表
							self._ziList = [zi for zi in self._corpus]        #去重后的中文字集
							self._ziSet = set(self._ziList)        #用于储存中文字及其出现在语料中的概率
							self._ziFreq = dict()        #用于储存字在语料中的位置
							self._ziIndex = dict()  #{zi1:[index1,...], zi2:[index1...]...}
							#用于储存语料中"字对"及 "字对的概率"        self._pair = dict()  #形如{(zi1,zi2):weight,...}
						
					
				

二、中文字集中每个字及其频率

					def Set(self):    corpus_len = self._corpusLen    zi_list = self._ziList    zi_set = self._ziSet    for zi in zi_set:        zi_freq = zi_list.count(zi)        self._ziFreq[zi]=zi_freq/corpus_len
				

三、每个汉字在语料中出现的位置

					
						def generate_index(self):    for index,zi in enumerate(self._corpus):
						if zi in self._ziIndex.keys():            self._ziIndex[zi].append(index)        else:
						self._ziIndex[zi]=[]            self._ziIndex[zi].append(index)
					
				

四、字对出现的个数

					
						def generate_pair(self):    #计算每个字对出现次数
						for zi,indexList in self._ziIndex.items():        for index in indexList:            if 1<= index <=self._corpusLen-2:
						b_zi = self._corpus[index-1]                a_zi = self._corpus[index+1]                if (b_zi, zi) in self._pair.keys():
						self._pair[(b_zi, zi)]+=1                else:                    self._pair[(b_zi, zi)]=1
						if (zi, a_zi) in self._pair.keys():                    self._pair[(zi, a_zi)]+=1                else:
						self._pair[(zi, a_zi)]=1
					
				

五、每个字对出现的频率

					
						def pair_gailv(self):         #计算每个"字对"在语料中出现的频率
						count = 0    for value in self._pair.values():        count=count+value    for k,v in self._pair.items():        self._pair[k]=v/count
					
				

五、语料中所有字对及概率从大到小输出

					
						def
						output
						(
						self
						):
						self
						.
						Set
						()
						self
						.
						generate_index
						()
						self
						.
						generate_pair
						()
						self
						.
						pair_gailv
						()
						
							#对结果按照概率由大到小排序
							self._pair = sorted(self._pair.items(), key=lambda x: x[1], reverse=True)    data = ['%s%s %.20f' % (k[0], k[1], v) for k, v in self._pair]    return data
						
					
				

测试

我下载了本小说《重生之2006》(额,追了快一年了)当做中文语料(其实这也太随意了,真实情况的语料可能都得上G)。在这里顺便测试下运行时间。

					
						import timedef test(input,output,encode):    start = time.time()    text = open(input,'r',encoding=encode).read()
						bayes = Bayes(text)    bayes.Set()    data = bayes.output()    f = open(output, 'w', encoding='utf-8')    for word in data:
						f.write(word+'\n')    f.close()    end = time.time()    duration = end-start    print(duration)input = r'/Users/suosuo/Downloads/重生之2006.txt'output = r'/Users/suosuo/Downloads/词频结果.txt'
						test(input,output,encode='gbk')
					
				

运行时间 352.6866388320923s. 输出的词频结果(由大到小),截图是前25个词。

小说的主角名叫 陆恒,主角女友 林素,主角开创的集团公司名 恒成,都出现在前25个词里,似乎效果很好。

无监督识别词语算法的Python实现

但打开词频结果.txt中间看,似乎就相当不准了。看来只能选取词频结果的较为靠前的部分的词才算靠谱词。其余的都无法靠谱的成词

无监督识别词语算法的Python实现

End.

转载请注明来自36大数据(36dsj.com): 36大数据 » 无监督识别词语算法的Python实现

随意打赏

python 算法python算法
提交建议
微信扫一扫,分享给好友吧。