作者:邓旭东HIT
前几天写了《 简单的中文分词算法》,今天就用Python写个 伪分词算法实现。
说 伪分词是因为我这脚本其实并不能对文本进行分词,只是计算两个汉字组合成词的概率(由于是无监督,前期没有人工介入,识别词的能力大大降低。)。 比如 ‘中’、’过’、’国’三个字的组成的字对有
‘中过’、’中国’、’过国’、’国过’、’国中’、’过中’,这六个 字对中,很容易就看到只有 中国这个 字对是能成词,其余都不是词。但是如果给你100个、1000个字,你怎么知道其中的能成词的字对呢。所以这里就要用统计学,统计语料中各个字对的概率,一般概率大者的 字对 有很大可能性是一个词。
代码实现
一、初始化
importreclassBayes(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
五、语料中所有字对及概率从大到小输出
defoutput(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个词里,似乎效果很好。
但打开词频结果.txt中间看,似乎就相当不准了。看来只能选取词频结果的较为靠前的部分的词才算靠谱词。其余的都无法靠谱的成词
本文采用「CC BY-SA 4.0 CN」协议转载自互联网、仅供学习交流,内容版权归原作者所有,如涉作品、版权和其他问题请给「我们」留言处理。