打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

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

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

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

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

代码实现

一、初始化

  1. import re

  2. class Bayes(object):

  3.    def __init__(self,corpus):

  4.        #将语料只保留中文字符

  5.        self._corpus = ''.join(re.findall(r'[\u4E00-\u9FD5]+',corpus))

  6.        #语料文本长度

  7.        self._corpusLen = len(self._corpus)

  8.        #将语料切分为单字列表

  9.        self._ziList = [zi for zi in self._corpus]

  10.        #去重后的中文字集

  11.        self._ziSet = set(self._ziList)

  12.        #用于储存中文字及其出现在语料中的概率

  13.        self._ziFreq = dict()

  14.        #用于储存字在语料中的位置

  15.        self._ziIndex = dict()  #{zi1:[index1,...], zi2:[index1...]...}

  16.        #用于储存语料中"字对"及 "字对的概率"

  17.        self._pair = dict()  #形如{(zi1,zi2):weight,...}

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

  1. def Set(self):

  2.    corpus_len = self._corpusLen

  3.    zi_list = self._ziList

  4.    zi_set = self._ziSet

  5.    for zi in zi_set:

  6.        zi_freq = zi_list.count(zi)

  7.        self._ziFreq[zi]=zi_freq/corpus_len

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

  1. def generate_index(self):

  2.    for index,zi in enumerate(self._corpus):

  3.        if zi in self._ziIndex.keys():

  4.            self._ziIndex[zi].append(index)

  5.        else:

  6.            self._ziIndex[zi]=[]

  7.            self._ziIndex[zi].append(index)

四、字对出现的个数

  1. def generate_pair(self):

  2.    #计算每个字对出现次数

  3.    for zi,indexList in self._ziIndex.items():

  4.        for index in indexList:

  5.            if 1<= index <=self._corpusLen-2:

  6.                b_zi = self._corpus[index-1]

  7.                a_zi = self._corpus[index+1]

  8.                if (b_zi, zi) in self._pair.keys():

  9.                    self._pair[(b_zi, zi)]+=1

  10.                else:

  11.                    self._pair[(b_zi, zi)]=1

  12.                if (zi, a_zi) in self._pair.keys():

  13.                    self._pair[(zi, a_zi)]+=1

  14.                else:

  15.                    self._pair[(zi, a_zi)]=1

五、每个字对出现的频率

  1. def pair_gailv(self):    

  2.    #计算每个"字对"在语料中出现的频率

  3.    count = 0

  4.    for value in self._pair.values():

  5.        count=count+value

  6.    for k,v in self._pair.items():

  7.        self._pair[k]=v/count

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

  1. def output(self):

  2.    self.Set()

  3.    self.generate_index()

  4.    self.generate_pair()

  5.    self.pair_gailv()

  6.    #对结果按照概率由大到小排序

  7.    self._pair = sorted(self._pair.items(), key=lambda x: x[1], reverse=True)

  8.    data = ['%s%s %.20f' % (k[0], k[1], v) for k, v in self._pair]

  9.    return data

测试

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

  1. import time

  2. def test(input,output,encode):

  3.    start = time.time()

  4.    text = open(input,'r',encoding=encode).read()

  5.    bayes = Bayes(text)

  6.    bayes.Set()

  7.    data = bayes.output()

  8.    f = open(output, 'w', encoding='utf-8')

  9.    for word in data:

  10.        f.write(word+'\n')

  11.    f.close()

  12.    end = time.time()

  13.    duration = end-start

  14.    print(duration)

  15. input = r'/Users/suosuo/Downloads/重生之2006.txt'

  16. output = r'/Users/suosuo/Downloads/词频结果.txt'    

  17. test(input,output,encode='gbk')

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

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

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

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
万字长文:预训练词向量模型的方法、应用场景、变体延伸与实践总结
~~CORPUS _ 小许的语料天涯~~
RPA手把手<span style="color: rgb(0, 0, 0); font-size: 14px; font-weight: 400;">python 词
收藏 | 中文公开聊天语料库及使用方法(附链接)
python – 查找所有常见的非重叠子字符串
Gensim进阶教程:训练word2vec与doc2vec模型
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服