如:
张三:
请明天下午三点到操场集合,我们一起打篮球。
李四
提取结果:
人物:李四 张三 事件:打篮球 地点:操场 时间:明天下午三点
先占坑 具体描述和过程先看github(https://github.com/GaoPeng97/naive-event-extraction-from-email) 里面有详细的介绍,记得star啊 ,debug不易。。。且码且珍惜
博客等考完试再写。。。复习去了
更新如下:
naive-event-extraction-from-email
github:https://github.com/GaoPeng97/naive-event-extraction-from-email
一、分析与实验
思路概要:通过调研发现我们想做的效果很接近NLP中一个经典的问题NER,NER又称命名实体识别,通常指的是从文本中提取哪些具有特别意义或者指代性非常强的实体,包括人名,地名,机构名,时间,专有名词等。而人名,地名,和时间恰恰也是我们想提取出来的。所以我们的首要目标应当是搭建一个NER系统。但是我们的目标却不只是提取这些地名,人名,我们还需要文本中提炼出事件,者是一个很棘手的事情,因为事件是一个很宽泛的概念,它可以是名词,动词,动名词等等。我们最后采用的是用TFIDF方法,从文本中得到重要性最高的名词,动词集合,从中得到事件的表达。
我们的实验步骤主要分为以下内容:
- 邮件的预处理
- NER系统
- 语料库及语料库的预处理
- HMM模型
- CRF模型
- NER系统结果
- TFIDF方法提取事件
- 提取内容导入日历
接下来也会根据以上思路展开叙述。
1、邮件的预处理
邮件的基本格式一般如下,我们再做实验时,也默认所有邮件都是如下格式:
尊敬的张三老师:
请您明天下午5点,到301教室开会。
李四
很容易想到的是直接将第一句,最后一句作为人名直接提取,虽然这样比较直接,但是我们并不是这种思路,我们是先用jieba分词将敬语和名字前的形容词去除,得到sender和receiver。然后将句子内容中的您、你、我、我们这种代词直接用receiver和sender替换。
代词 替换词
我 sender
你 receiver
您 receiver
我们 sender and receiver
对于时间,我们先读取当地时间MM/DD,然后将文本中的今天、明天对应替换。
时间词 替换词
今天 MM/DD
明天 MM/DD + 1
所以例子中得到的预处理结果就会是:(假如今天是1月1日)
请张三1月2日下午5点,到301教室开会。
然后将该结果继续进行下一步操作。
2、NER系统
方法选择:
对于NER任务通常使用的有基于规则和基于模型的方法。
基于规则:
基于规则适合实体本身有很多特征的情况,方法简单且有效。比如抽取物品价格时,基本都是“数字+元”的形式,直接找到 ’ 元 ‘ 将前面的数字提取即可。但随着场景和表达越来越复杂,当出现 “一千万”, “两块五”这种形式时,就不太实用了。所以基于规则的方式主要是适用于比较规范和结构化的文本抽取任务。
基于模型:
如果从模型的角度,NER问题实际上就是序列标注的问题。序列标注问题是指模型的输入是一个序列,对于输入序列的每一个单元,输出特定的标签,如BIO模型,B表示这个字是词的开始,I是词的其他部分,o表示非该词的部分。数列标注问题可以涵盖NLP中很多任务,包括语音识别,中文分词,命名实体识别等。常用的模型有HMM,CRF。
综合考虑,基于规则的方法约束太大,用基于模型的方法更适合我们的题目。
语料库的处理:
基于调研我们最终选择了人民日报1998年语料库,该语料库是对纯文本预料进行了词语切分和词性标注而成的,文章中每个词语都带有词性标记,包括名词n、时间词t、处所词s、量词q、等40多种词性,其中还包括方便语料库应用的专有名词人名nr、地名ns、机构名nt。考虑到我们的目标是将文本中的地名,人名,机构名和时间处理,所以有很多标注对我们而言是无用的,所以我们需要先对语料库进行预处理:
1、姓名的合并:
原有语料库中,姓和名是分开标注的,我们需要将姓名和并如
周/nr 恩来/nr -----> 周恩来/nr
2、时间类合并
原有语料库中的时间也是分开标注的,也需要合并:
1998年/t 12月/t 1/日 ------------> 1998年12月1日
3、中括号括起来的词表示大粒度分词,表达能力更强,需要合并
[中国/ns 政府/n]nt ------------> 中国政府/nt
4、全角字符统一转为半角字符
全角占两个字节,半角站一个字节,主要是要对数字和标点符号进行处理,转成半角。
部分语料库处理前后对比:
模型的训练
我们综合考虑了两种模型,并分别进行测试。
CRF模型
用CRF模型进行训练时,我们主要用了有以下几个步骤:
- 确定标签体系
- 确定特征模板
- 模型训练
1、确定标签体系:
从下图中可以很容易看出不同标签体系的区别。(注:图片来源于网络)
显而易见的是,标签体系越复杂准确度也越高,相应的训练时间也会增加。我们最后选择的是BIO标签体系。
2、特征模板的设计
特征模板的我们也选用了简单的方式就是选用了该词的前一个,后一个,前一个和当前的和,当前和后一个的和:
3、模型训练
我们使用的是sklearn-crfsuite工具包,参考官方文档得到训练方法如下
训练结果有:
HMM模型:
主要步骤如下
- 输入要测试的单句,调用hmm_nerf_tagger函数
- 根据语料库文件,实例化HMM类。对语料库进行处理,调用HMM类中get_word_tag:读取语料库中的字和相应标签; get_tag_tag:读取标签的转移状态;get_words(self):读取语料库中的所有字,写成文件
- 若所需要的参数文件(emiss_prob.txt,trans_prob.txt,start_prob.txt)未存在于当前路径中,则调用get_start_prob,统计初始概率get_transition_probability,统计转移概率,get_emission_probability,统计发射概率,得到相应的参数文件
- 若所需要的参数文件存在,则调用get_observation方法将句子处理成列表,并用load_start_pro,load_emission_pro,load_transition_pro读取初始概率,发射概率和转移概率。
流程图如下:
得到训练结果如下:
综合分析,HMM是一种生成模型,对部分实体识别率不高,如机构名,识别甚至不到50%,整体要比判别模型CRF低。所以我们最后采用了CRF模型来进行NER识别。
3、TFIDF提取事件
正如上文中所提到的,事件无法给出一个精确的定义,但是就我们日常生活中来看,大部分具有真实含义的动名词或者是名词都能准确的表达邮件的主旨,比如在学校日常的“考试”、“开会”、“上课”、“打篮球”等都是简单的名词或者动名词,所以我们认为再学校这个大的背景前提下,动词或者名词就能够描述事件了,但是一般一封邮件中名词,动词、动名词都不止一个,如何判断那个才是我们需要的?我们就采用了TFIDF方法来判断词的重要性,然后去除重要性排列中所有已经NER出来的关键词,然后再选取重要性最高的候选词描述事件。
TFIDF原理
TFIDF(Term Frequency-Inverse Document Frequency)即词频-逆文件频率,是一种统计方法,用于统计一个字对于一个文件集或一个语料库中的其中一份文件的重要程度,字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的文档数反比下降。总结来说就是,当一个词对于一个文档越重要,他在该文档中出现的次数就应该越多,在其他文档中出现的次数就应该越少。
- TF: (Frequency Term,TF) 指的是某一个给定的词语在该文件中出现的次数。需要归一化,因为越长的文档越容易出现更多次数的关键词。公式为 TF = \frac {某词条在文档中的出现次数} {该文档中所有词条数目}
- IDF: (Inverse document frequency, IDF)指的是,如果包含该词条的文档越少,IDF越大,说明词条具有很好的类别区分能力。所以某个特定词的IDF可以有总文件数目初一包含该词语的文件数目,再将商取对数得到: IDF = log(\frac {文档总数} {包含词条的文档数 + 1})
- TF-IDF: TFIDF = TF*IDF
根据上述原理,我们直接使用了别人已有的idf.txt,统计了每个词的逆文件频率,然后根据我们的情形适当加大“打球”,“开会”,“考试”这种和学校相关性比较大的词的数值,提升效果。然后处理我们的文本,把一些 ‘的’ ‘了’ 之类的无意义的停用词去除,再把已经用NER打上标签的词去除,将余下的词用TFIDF方法排序即可以得到表达事件的词。
4、导入日历
主要是参考了google日历的api(https://developers.google.com/calendar),编写我们插入事件的模块,注意在使用的时候,一定要将credential.json拷贝进文件夹,然后删除token.json重新运行会得到适配自己账户的token.json。