前几天写了《简单的中文分词算法》,今天就用Python写个 伪分词
算法实现。
说 伪分词
是因为我这脚本其实并不能对文本进行分词,只是计算两个汉字组合成词的概率(由于是无监督,前期没有人工介入,识别词的能力大大降低。)。 比如 '中'、'过'、'国'
三个字的组成的字对有
'中过'、'中国'、'过国'、'国过'、'国中'、'过中'
,这六个 字对
中,很容易就看到只有 中国
这个 字对
是能成词,其余都不是词。但是如果给你100个、1000个字,你怎么知道其中的能成词的字对呢。所以这里就要用统计学,统计语料中各个字对的概率,一般概率大者的 字对 有很大可能性是一个词。
一、初始化
import re
class 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 time
def 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.6866388320923
s. 输出的词频结果(由大到小),截图是前25个词。
小说的主角名叫 陆恒
,主角女友 林素
,主角开创的集团公司名 恒成
,都出现在前25个词里,似乎效果很好。
但打开词频结果.txt中间看,似乎就相当不准了。看来只能选取词频结果的较为靠前的部分的词才算靠谱词。其余的都无法靠谱的成词
联系客服