基于依存句法分析的关键短语抽取算法实战
由于最近在做一些无监督的关键词短语(实体)抽取工作,其实最大的背景还是没有标注好的实体识别训练数据;所以想到采用无监督的关键短语抽取算法折中去抽取一些实体,于是调研了一波关键短语抽取算法和工具。目前无监督关键短语抽取算法和关键词抽取算法差不多:主要是TFIDF,Textrank 等特征为候选短语的打分。然后抽取得分高的候选短语。
算法流程
关键词短抽取成算法主要分为两部分:1.候选短语抽取;2.候选短语打分
- 候选短语抽取:一般可以采取 "ngram" + 文法规则的做法:比如下方例子中的2gram短语中,[股价_n,创_v ] 中名词(n)后面接动词(v)很显然就不是一个合理的短语,不应该被召回到候选词集合中。而[阿里_ns,市值_n] 中 地名(ns)后面接名词就是个合适候选短语。
- 候选短语打分:通过上述ngram + 文法规则我们召回候选词集合后,之后我们就可以通过 词语的TFIDF,Textrank等权重特征的给短语打分,当然你也可以用一些其他的文本特征给词语打分。总之,最后我们通过各种特征可以计算出每个短语的得分,然后排序后取topk得候选短语就可以得到我们的关键短语了。
引入依存句法分析
依存句法分析这里笔者不做过多的介绍,有兴趣的同学可以去百度一波.但是这里笔者展示一下依存句法分析的结果,通过依存句法分析,我们可以得到一颗如下的依存树,树的每条边记录了连接节点的对于关系,比如 “青年”的定语是“男性”,所以青年和男性是定中关系。具有定中关系的相邻词组就是一个短语,同时被修饰的词通常比较重要(这是笔者的一个假设),所以,笔者认为:具有定中关系的相邻词组是关键词。
dependency tree下方是笔者在百度百科中搜索出来的“借款费用”的定义,用依存句法分析了一波,也确实发现具有定中关系的词组组合起来就是关键短语,比如:借款费用,借款利息,外币借款等。
"借款费用是企业因借入资金所付出的代价,包括借款利息、折价或者溢价的摊销、辅助费用以及因外币借款而发生的汇兑差额等"
的依存句法分析结果如下:
1,借款-->定中关系-->2 ,费用
2,费用-->主谓关系-->3 ,是
3,是-->核心关系-->0 ,##核心##
4,企业-->主谓关系-->9 ,付出
5,因-->状中结构-->9 ,付出
6,借入-->介宾关系-->5 ,因
7,资金-->动宾关系-->6 ,借入
8,所-->左附加关系-->9 ,付出
9,付出-->定中关系-->11 ,代价
10,的-->右附加关系-->9 ,付出
11,代价-->动宾关系-->3 ,是
12,,-->标点符号-->3 ,是
13,包括-->并列关系-->3 ,是
14,借款-->定中关系-->15 ,利息
15,利息-->动宾关系-->13 ,包括
16,、-->标点符号-->17 ,折价
17,折价-->并列关系-->15 ,利息
18,或者-->左附加关系-->21 ,摊销
19,溢价-->定中关系-->21 ,摊销
20,的-->右附加关系-->19 ,溢价
21,摊销-->并列关系-->17 ,折价
22,、-->标点符号-->23 ,辅助
23,辅助-->定中关系-->24 ,费用
24,费用-->并列关系-->21 ,摊销
25,以及-->左附加关系-->33 ,差额
26,因-->状中结构-->30 ,发生
27,外币-->定中关系-->28 ,借款
28,借款-->介宾关系-->26 ,因
29,而-->状中结构-->30 ,发生
30,发生-->定中关系-->33 ,差额
31,的-->右附加关系-->30 ,发生
32,汇兑-->定中关系-->33 ,差额
33,差额-->并列关系-->21 ,摊销
34,等-->右附加关系-->13 ,包括
实战部分
实战部分笔者的思路如下:
- 首先采用传统的关键词词组抽取算法抽取一下句子中的关键词短语(可以有效抽取一些新词和关键短语),这样防止一些专有名词分词错误,这里你也可以采用实体识别算法。然后将新抽出的新词加入用户词典。
- 然后采用依存句法分析得到句子的依存树,将具有定中关系的相邻词组抽取出来。
关键短语抽取推荐使用:ckpe 这个工具库,作者引入了LDA主题模型去优化关键短语打分,效果不错。
至于依存句法分析:笔者选择的是hanlp。
代码如下:
from pyhanlp import *
import ckpe
def extract_key_phrase(sentence):
key_phrase = []
ckpe_obj = ckpe.ckpe()
entity = ckpe_obj.extract_keyphrase(sentence,top_k=10)
for i in entity:
CustomDictionary.insert(i)
print(entity)
tree = HanLP.parseDependency(sentence)
for word in tree.iterator(): # 通过dir()可以查看sentence的方法
print("%d,%s-->%s-->%d ,%s" % (word.ID, word.LEMMA, word.DEPREL, word.HEAD.ID, word.HEAD.LEMMA))
if word.DEPREL == "定中关系":
key_phrase.append(word.LEMMA + word.HEAD.LEMMA)
return [ phrase for phrase in key_phrase if phrase in sentence]
输入一下句子:
sentence= "借款费用是企业因借入资金所付出的代价,包括借款利息、折价或者溢价的摊销、辅助费用以及因外币借款而发生的汇兑差额等"
extract_key_phrase(sentence)
最后结果如下:
- ckpe的抽取结果为:['外币', '差额', '费用', '利息', '代价', '资金', '企业']
- ckpe + 依存树 的结果为: ['借款费用', '借款利息', '辅助费用', '外币借款', '汇兑差额']
结论
所以在关键短语抽取算法中引入依存句法分析似乎有着不错的效果,其实也是利用了句法特征。做为一个nlper 如果能够善于使用词性特征,句法特征等这些传统特征也能够做很酷的事情,比如无监督抽取出这么好效果的关键短语。当然无监督会产生较多的错误,我们可以采用这种算法辅助去标注数据,最终通过有监督的深度模型训练达到最佳效果。
参考
https://github.com/dongrixinyu/chinese_keyphrase_extractor
https://mp.weixin.qq.com/s/fBSEtM4gQ6-5jQpy0JaQvw