一种没有语料字典的分词方法

2024-02-04 23:50

本文主要是介绍一种没有语料字典的分词方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

前几天在网上闲逛,看到一篇美文,说的是怎么在没有语料库的情况下从文本中提取中文词汇,理论部分讲得比较多,但都还是很浅显易懂的,其中涉及一部分信息论的理论,其实只要大学开过信息论这门课的话,看起来还是挺简单的。

信息论我忘得差不多了,但是其中主要的内容还记得,信息论最主要的就是信息其实是可以度量的,一个事件包含的信息和它发生的概率成反比,简单的说,同样一个事件,产生A结果的概率为Pa,产生B结果的概率为Pb,如果Pa大于Pb,那A所包含的信息量就比B要大。

打个简单的比喻,比如中国队和西班牙队踢足球比赛,大家都知道,西班牙队赢的概率大概是99.9999%,中国队赢的概率大概是0.0001%,假如最后的结果是中国队赢了(靠实力)的话,那这个事件(中国队赢了西班牙)就是个信息量非常巨大的事件,我相信各大报纸的头条都会报道,反而如果西班牙赢了,估计没有报纸会报道这个消息,这就是信息论的核心,也就是信息熵。

扯远了,上面只是说说我对信息论的理解,在分词技术上,目前的分词技术基本上都是基于字典的,就是看文章中有没有字典含有的词语,如果有,就把这个当成一个词来分,这样也衍生了很多分词技术,大家有兴趣可以自己去查一查。

如果我们没有词典,需要分词就比较麻烦了,假设我们最大的词长度设定为5,能想到的办法就是,从第一个字开始,把文本中所有连在一起的两个字,三个字,四个字,五个字的片段找出来,然后看这些片段在文本中出现的频率,频率高的就当成一个词汇,这样确实能分出词来,但是这样同样也分出了一些不是词的词汇,比如上面的文章中,“的话”这个词就出现的相对比较多,显然,这不是一个词。

在这种基础上怎么把类似“的话”这样的词去掉就是我们要做的工作了。这涉及到两个重要的部分,也是那篇美文提到的两个部分。

第一,怎么去掉类似于“的中国”和“中国队”这样的差异,这三个词可能出现的频率都差不多,甚至“的中国”出现的频率更高,假设对于一个长文本(假设为10000,并且是描述足球比赛的),
“的中国”出现了100次,概率是1%
“中国队”出现了60次,概率是0.6%
“中国”   出现了200次,概率为2%
“的”       出现了500次,概率为5%
“队”       出现了70次,概率为0.7%
这样的数据情况下,“的”字和“中国”随机组合在一起的概率为5%*2%=1%,而“队”和“中国”随机组合在一起的概率为0.7%*2%=0.14%,显然“的中国”的出现概率和他们组合在一起的概率差不多,所以我们认为“的中国”更像是随机组合在一起的词而不是一个固定的词汇,但“中国队”出现的概率比他们组合在一起的概率高了4.28倍,所以我们认为“中国队”更像一个词汇。
通过上面的计算,我们就可以把“的中国”这样的词丢掉了,就算他出现了很多次,但是我们一样不认为它是一个词,这就是第一部分,我们把它叫词语的凝聚程度,“的中国”显然凝聚力不够。


第二,像类似“了一”这样的词在文章中肯定也出现得很多,因为是足球比赛文章,所以经常出现摔了一跤,进了一球等等,显然,“了一”也不是一个词汇,但是单独看“了”和“一”,“了一”的概率可能比他们单独组合的概率高不少,像这样的词怎么弄呢,这就要用到开头我们讲的信息论中的信息熵了。

“信息熵”能够反映知道一个事件的结果后平均会给你带来多大的信息量。如果某个结果的发生概率为 p ,当你知道它确实发生了,你得到的信息量就被定义为 - log(p) 。 p 越小,你得到的信息量就越大。在“了一”这个词中,他的前缀为“摔”,“进”,概率分别是p1,p2那他的前缀信息熵就是- log(p1)*p1-log(p2)*p2,同样后缀的信息熵也可以算出来,算出来以后我们取其中较小的那个作为这个词的前后缀信息熵,结果算出来是一个非常小的数,比如0.2,比普通真实的词汇,比如“摔了一跤”这样的词的信息熵都要小,所以显然可能“了一”就不是一个词汇了,反而“摔了一跤”这样的词更像一个词汇。

有了这两个理论,那我们找出一个词,然后按这两个条件给出一个阈值,就能抽取出一批我们认为是词汇的词语了,不需要字典,而且从抽取出来的词根据词频排列的话,再把一般性的词如“应该”,“如果”,“似乎”这样的介词去掉的话,一般是这个文本的关键字集合了。

嗯,理论部分大概就是这样了,具体的大家要是有兴趣,可以看看这篇blog,我都是看到这个的,顺便推荐一个这个作者,他的文章基本上都是原创,而且对数学理解得很到位,很适合各种程序猿们,呵呵。
http://www.matrix67.com/blog/archives/5044

按照这个东西,我自己写了个python脚本,写得很着急,而且不知道理论理解得对不对,后来我对《明朝那些事》抽了一把,出现了这些:
危险 优秀沉默李景隆影响 杨继盛 痛苦 脑袋 徐有贞厉害支持 蓝玉杨廷和瓦剌申时行 判断 记载 孙承宗坚持愤怒奏疏 锦衣卫 严世蕃 祁钰 倭寇 东林党麻烦朋友 努尔哈赤  选择喜欢容易 首辅 御史李如松 父亲戚继光投降 陈友谅 厚照 希望 蒙古简单估计消息彻底 胡宗宪 祁镇 毕竟 魏忠贤 告诉 袁崇焕 嘉靖 似乎 准备 。。。。。。。。

而对于《时间简史》,出现了这些:
空间时间 吸引增加基本尺度 效应 东西描述轨道
位置 边界产生解释夸克 广义相对论坍缩 辐射 部分
知道 状态区域距离爆炸 问题 奇点模型太阳
事件 科学预言运动膨胀 任何 必须恒星黑洞.......

你修改约束条件,就会出现不同的词语,怎么平衡这个约束条件也是个问题。

另外,如果你有兴趣,可以分析分析一些人的blog和微博之类的,再和你自己的对比一下,说不定能找到很多关键词一样哦,还有,要是你有海量的数据,也可以做一些非常有意思的事情哦,哈哈。


最后,再次推荐一下matirx67的blog:  http://www.matrix67.com/     


程序做得太快了,不好,还是把关键函数贴出来吧,就是暴力的编码,用了python自带的方便的数据结构来快速开发。所以速度上比较慢,而且内存上。。呵呵。。说不定会爆哦。。。。完整程序:
https://github.com/wyh267/ChineseWordSegmentation

# -*- coding=utf-8 -*-
'''
Created on 2013-5-9@author: Wu YingHao@email:  wyh817@gmail.com该程序可以在没有语料库的情况下从文本中抽取出中文词汇
理论支持:
http://www.matrix67.com/blog/archives/5044'''import math"""计算每个字和词的出现频率输入: words 字符串内容num 需要截取的最长字串输出: split_words 分割好的所有子串的数据,以字典形式返回split_words 说明{"字串" : [ 出现次数,出现概率,凝固程度,凝固程度*出现次数,自由程度,前缀集合,后缀集合] .....}
"""
def find_words(words,num=6):split_words={}lens=len(words)for i in range(0,lens):for j in range(1,num+1):if i+j < lens -num-2:if words[i:i+j] in split_words:split_words[words[i:i+j]][0]+=1split_words[words[i:i+j]][1]=float(split_words[words[i:i+j]][0])/float(lens)split_words[words[i:i+j]][6].append(words[i-1])split_words[words[i:i+j]][7].append(words[i+j])else:split_words[words[i:i+j]]=[1,1/float(lens),words[i:i+j],1,1,0,[words[i-1]],[words[i+j]]]if(i%10000==0):print "完成 :" + str(float(i)/float(len(words))*100) + " %"return split_words"""计算凝聚程度输入:words_dic 已经拆分好的字符串字典输出:填充好凝聚程度的字典
"""
def find_nh(words_dic):for key in words_dic.keys():if(len(key)>1):#左凝聚程度left_p=words_dic[key][1]/(words_dic[key[:1]][1]*words_dic[key[1:]][1])#右凝聚程度right_p=words_dic[key][1]/(words_dic[key[:-1]][1]*words_dic[key[:-1]][1])if(left_p<right_p):words_dic[key][3]=left_pelse:words_dic[key][3]=right_p"""计算自由程度输入: word_dic 字典文件返回:word_dic 添加自由程度以后的字典
"""
def calc_free(word_dic):for key in word_dic.keys():front_free=0end_free=0for front in word_dic[key][6]:if front in word_dic:front_free-=math.log(word_dic[front][1])*word_dic[front][1]for end in word_dic[key][7]:if end in word_dic:end_free-=math.log(word_dic[end][1])*word_dic[end][1]if(front_free < end_free):word_dic[key][5]=front_freeelse:word_dic[key][5]=end_freereturn word_dic  


注:本文虽然不是转帖,但是内容参考了matrix67的博客,地址为  http://www.matrix67.com/blog/archives/5044  ,特此声明。


===========================================================================================
欢迎大家关注我的微信号: XJJ267    西加加语言
或者扫描下面的二维码也行哦。


转载于:https://my.oschina.net/wuyinghao/blog/666146

这篇关于一种没有语料字典的分词方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/679172

相关文章

Python中的魔术方法__new__详解

《Python中的魔术方法__new__详解》:本文主要介绍Python中的魔术方法__new__的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、核心意义与机制1.1 构造过程原理1.2 与 __init__ 对比二、核心功能解析2.1 核心能力2.2

Python Transformer 库安装配置及使用方法

《PythonTransformer库安装配置及使用方法》HuggingFaceTransformers是自然语言处理(NLP)领域最流行的开源库之一,支持基于Transformer架构的预训练模... 目录python 中的 Transformer 库及使用方法一、库的概述二、安装与配置三、基础使用:Pi

关于pandas的read_csv方法使用解读

《关于pandas的read_csv方法使用解读》:本文主要介绍关于pandas的read_csv方法使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录pandas的read_csv方法解读read_csv中的参数基本参数通用解析参数空值处理相关参数时间处理相关

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Java中使用Hutool进行AES加密解密的方法举例

《Java中使用Hutool进行AES加密解密的方法举例》AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个,下面:本文主要介绍Java中使用Hutool进行AES加密解密的相关资料... 目录前言一、Hutool简介与引入1.1 Hutool简介1.2 引入Hutool二、AES加密解密基础

Pytest多环境切换的常见方法介绍

《Pytest多环境切换的常见方法介绍》Pytest作为自动化测试的主力框架,如何实现本地、测试、预发、生产环境的灵活切换,本文总结了通过pytest框架实现自由环境切换的几种方法,大家可以根据需要进... 目录1.pytest-base-url2.hooks函数3.yml和fixture结论你是否也遇到过

鸿蒙中Axios数据请求的封装和配置方法

《鸿蒙中Axios数据请求的封装和配置方法》:本文主要介绍鸿蒙中Axios数据请求的封装和配置方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.配置权限 应用级权限和系统级权限2.配置网络请求的代码3.下载在Entry中 下载AxIOS4.封装Htt

jupyter代码块没有运行图标的解决方案

《jupyter代码块没有运行图标的解决方案》:本文主要介绍jupyter代码块没有运行图标的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录jupyter代码块没有运行图标的解决1.找到Jupyter notebook的系统配置文件2.这时候一般会搜索到

Redis实现延迟任务的三种方法详解

《Redis实现延迟任务的三种方法详解》延迟任务(DelayedTask)是指在未来的某个时间点,执行相应的任务,本文为大家整理了三种常见的实现方法,感兴趣的小伙伴可以参考一下... 目录1.前言2.Redis如何实现延迟任务3.代码实现3.1. 过期键通知事件实现3.2. 使用ZSet实现延迟任务3.3

idea maven编译报错Java heap space的解决方法

《ideamaven编译报错Javaheapspace的解决方法》这篇文章主要为大家详细介绍了ideamaven编译报错Javaheapspace的相关解决方法,文中的示例代码讲解详细,感兴趣的... 目录1.增加 Maven 编译的堆内存2. 增加 IntelliJ IDEA 的堆内存3. 优化 Mave