大数据:无监督识别词语算法的Python实现

标签:大数据IT数据

访客:26040  发表于:2017-05-27 09:48:10

前几天写了《简单的中文分词算法》,今天就用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个词里,似乎效果很好。


大数据

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


大数据

来源:36大数据 作者:邓旭东HIT

评论(0)

您可以在评论框内@您的好友一起参与讨论!

<--script type="text/javascript">BAIDU_CLB_fillSlot("927898");