关键词提取
关键词提取的应用
在大数据时代,如何在浩如烟海的纷杂数据中提取出有价值的信息,将数据转化为宝贵的资源非常重要。在文本领域,我们当然无法依靠肉眼去获取其中的关键信息,因此关键词的自动化提取也是自然语言处理中重要且基础的研究内容。那么,具体地,关键词提取有哪些应用呢?这里给大家举几个案例:
知识管理:如今,在线提供的信息比以往任何时候都多,但是,其中 80% 的数据都是非结构化的,这意味着它们是杂乱无章,难以搜索及难以处理的。在某些领域如科学研究和医疗保健,堆积着大量的非结构化信息,因此浪费了其巨大的价值潜力。关键字提取使所有行业都能轻松搜索,管理和访问相关内容,从而发现新知识。例如,医生和临床医生需要进行研究以找到相关证据来支持其医疗决策。即使有非常多可用的数据,也很难在医学文献的海洋中找到最相关的数据。从文本中自动提取最重要的关键字和关键短语能够节省宝贵的时间资源。
商业情报:关键字提取对于商业智能场景也很有用,例如市场研究和竞争分析。可以利用从产品评论到社交媒体等各种来源的信息,帮助了解目标市场的痛点并做出以数据为依据的决策,以改善产品或服务。比如通过分析酒店评论,根据其中的关键词提取来发现酒店的问题,以改进酒店的设施、服务等方面。
舆情分析:如今人们使用社交媒体表达对各种实事的想法,感受和观点,比如体育赛事、总统竞选、娱乐八卦、科技发展等等。比如在美国大选期间,可以通过提及总统候选人的推文,借助关键字提取,分析民众的偏好以及对候选人的认知,辅助民意调查。
基于特征统计的关键词提取
为什么一篇新闻的标题常使用黑体并且字号偏大?当然是为了引人注目。反之,也可以得出一个结论,文本中颜色明显而且字号大的部分很可能是关键信息。所以,根据对词本身及词相关特征的统计及分析,可以评估一个词的重要程度。这种方法可解释性强,而且计算便捷,以下整理了一些用于评估重要性的常见指标。
词频:一般来说,一个词在文本中出现次数越多,表明作者越想表达这个词,因此可以通过对词频的简单统计便可以评估出词语的重要性。当然,这种做法并不严谨,存在一些漏洞,比如“的”、“了”、“吗”之类的介词、助词、语气词等在很多文本中都频繁出现,却不是重要信息;又比如某些词很重要,但可能只在开头出现了一次,之后用指代的方式进行描述,类似“川普…他…这个人…他”的形式。
TF-IDF(term frequency–inverse document frequency):综合考虑了词在文本中的词频以及普遍重要性,直观地说,一个词在其它文本中出现越少,在本文本中出现越多,那么对此文本的重要性越强。例如有一个文本中,“石墨”和“实验”这两个词出现次数都很多,但是前者在其它文本中出现很少,而后者在其它文本中也经常出现,根据 TF-IDF 的算法,表明“石墨”比“实验”在本文中更关键。
位置特征:在做阅读理解的时候,老师常常教我们要仔细留意标题、副标题、摘要、导语、文首文末等地方的信息,这说明词出现的位置与其重要性也有紧密关联。
词跨度:指的是一个词在文本中首次与末次出现的距离,距离越长,说明重要性越大。比如,小说中的主人公都是活到最后的,主人公对应的词跨度都很长。
词的固有属性:包括一系列特征,词长、词性、对应的句法成分、开头大小写、是否全部大小写、词缀等。例如在一般情况下,名词和动词在文本中相对重要,有特定情况下形容词比较重要,如对于某商品的评价文本、对于一些物品的宣传文本等。
这些指标都有各自的理论基础及实践意义,但也存在一些缺陷。在大多数情况下,研究者们会根据具体的场景,搭配组合使用各项特征。接下来基于以上要点做一些实验。
首先,最简单粗暴的方法是统计文本中的词频,基于词频选出 top5 作为关键词。
# 基于词频
import jieba
import collections
text = "关键词是能够表达文档中心内容的词语,常用于计算机系统标引论文内容特征、信息检索、系统汇集以供读者检阅。关键词提取是\
文本挖掘领域的一个分支,是文本检索、文档比较、摘要生成、文档分类和聚类等文本挖掘研究的基础性工作。"
count = collections.Counter(jieba.lcut(text)) # 分词及计算词频
count = sorted(count.items(), key=lambda x: x[1], reverse=True) # 按词频排序
count[:5] # 取 top5 作为关键词
显然,“、”,“是”,“的”并不算是关键词,因此考虑去除一些停用词,即没什么实际意义的词汇,这里所用的是哈工大的停用词表 hit_stopwords.txt。
# 基于词频,去除停用词以及标点符号
!wget -nc "https://labfile.oss.aliyuncs.com/courses/3205/hit_stopwords.txt"
with open("hit_stopwords.txt", "r", encoding="utf8") as f:
# 获取停用词(其中也包含了标点符号)
stopwords = [w.strip() for w in f.readlines()]
words = [word for word in jieba.lcut(
text) if word not in set(stopwords)] # 分词及过滤停用词
count = collections.Counter(words) # 计算词频
count = sorted(count.items(), key=lambda x: x[1], reverse=True) # 按词频排序
count[:5] # 取 top5 作为关键词
当然,假如我们更关注文本中的动作、行为,还可以指定关键词的词性,即动词相关的词汇来筛选。
# 基于词频,去除停用词以及标点符号,并且指定词性
from jieba import posseg
with open("hit_stopwords.txt", "r", encoding="utf8") as f: # 获取停用词(其中也包含了标点符号)
stopwords = [w.strip() for w in f.readlines()]
v_types = {'v', 'vd', 'vn', 'vf', 'vx', 'vi',
'vl', 'vg'} # jieba 词性标注中所有动词相关的词性符号
# print(posseg(text))
words = [i.word for i in posseg.cut(text) if i.word not in set(
stopwords) and i.flag in v_types] # 分词及过滤停用词,并且指定词性
count = collections.Counter(words) # 计算词频
count = sorted(count.items(), key=lambda x: x[1], reverse=True) # 按词频排序
count[:5] # 取 top5 作为关键词
应用 TF-IDF 提取文本中的关键词,调用 jieba 中 analyse.extract_tags() 函数即可,有以下几个关键参数:
topK: 返回几个 TF-IDF 权重最大的关键词,默认值为 20。
withWeight :是否返回关键词权重值,默认值为 False。
allowPOS: 仅包括指定词性的词,默认值为空,即不筛选。
import jieba.analyse
keywords = jieba.analyse.extract_tags(
text, topK=5, withWeight=False, allowPOS=())
keywords
同时返回关键程度( TF-IDF 值):
keywords = jieba.analyse.extract_tags(
text, topK=5, withWeight=True, allowPOS=())
keywords
限定关键词为名词:
keywords = jieba.analyse.extract_tags(
text, topK=5, withWeight=False, allowPOS=('ns', 'vn', 'n'))
keywords
基于主题模型的关键词提取
在讲解主题模型之前,先观察这样几句文本:
明明养了一只狗和一只猫。
一般来说,猫比狗要安静些。
多吃香蕉有利于肠胃健康。
柿子最好不要空腹吃,相比于香蕉,明明比较喜欢柿子。
如果单纯从词频分析的角度来看,狗、猫、香蕉、柿子可能是这几个文本的关键词。但进一步思考,可以发现这几个句子主要讲的是“动物”和“水果”这两个主题。主题模型的核心假设便是,存在隐含变量,即文本主题,决定了文本中词汇的出现情况。LDA(Latent Dirichlet Allocation)是最典型的主题模型,它假设语料库中蕴含了多个主题,而每个主题下面对应了一系列的词语。当作者在书写某篇文章时,是先设定某个主题再从中选择某个词的过程。
如下图所示,左侧表示一系列主题,每个主题下对应有相关词的概率分布,中间的直方图代表了文本中所蕴含主题的概率分布,这两类概率分布决定着文本中每一个词的出现情况。
在具体运算中,首先需要指定主题的数目,一般需要根据实验结果多次调节,主题模型根据文本中词的出现频率情况即词袋模型去学习两类概率分布,最后我们可以认为每个主题下概率较大的词汇为关键词。主题模型的数学理论十分扎实,涉及到贝叶斯理论、Dirichlet 分布、多项分布、图模型、变分推断、EM 算法、Gibbs 抽样等知识,非常适合用于无标签的大型文本数据的主题挖掘。
用通俗的语言解释主题模型,便是透过现象看本质。在生活中,我们会根据一个人的衣着外貌、学历职业等外在表现去判断这个人的本质。对应到主题模型,各个文档中词汇的出现情况便是外在表现,而我们感兴趣的本质便是文档中蕴含的主题,也可以称为隐变量、topic、concept 等,从这个层面而言,隐马尔科夫模型中的隐变量、神经网络中的中间层输出,其实都是那些重要的本质,不同的算法从不同的角度提出不同的方法建立外在与本质的联系,而主题模型应用了概率分布的方式去建立联系,即词汇与主题以及文档与主题的关系。
接下来基于 Gensim 库中封装好的主题模型进行关键词的提取。
# 首先进行文本处理
import jieba
texts = ["理论上,NLP是一种很吸引人的人机交互方式。",
"早期的语言处理系统如SHRDLU,当它们处于一个有限的“积木世界”,运用有限的词汇表会话时,工作得相当好。",
"这使得研究员们对此系统相当乐观,然而,当把这个系统拓展到充满了现实世界的含糊与不确定性的环境中时,他们很快丧失了信心。",
"由于理解(understanding)自然语言,需要关于外在世界的广泛知识以及运用这些知识的能力。",
"自然语言认知,同时也被视为一个人工智能完备(AI-complete)的问题。",
"同时,在自然语言处理中,理解的定义也变成一个主要的问题。",
"有关理解定义问题的研究已经引发关注。"]
# 将文本进行分词
words = [jieba.lcut(text) for text in texts]
from gensim import corpora, models
dictionary = corpora.Dictionary(words) # 构建词典
# doc2bow()方法将 dictionary 转化为一个词袋。
corpus = [dictionary.doc2bow(w) for w in words]
# 得到的结果corpus是一个向量的列表,向量的个数就是文档数。在每个文档向量中都包含一系列元组,元组的形式是(单词 ID,词频)
corpus
接下来进行主题模型训练,主要有以下几个重要参数:
num_topics :必选参数,表示要生成的主题个数。对于此参数的取值,一般是基于经验,主观判断、不断调试。
id2word :必选参数,表示 dictionary,即 id 与单词的映射关系。
passes :可选参数,表示模型遍历语料库的次数。遍历的次数越多,模型越精确。但是对于非常大的语料库,遍历太多次会花费很长的时间。
lda_model = models.ldamodel.LdaModel(
corpus=corpus, num_topics=2, id2word=dictionary, passes=10)
topic_words = lda_model.print_topics(num_topics=2, num_words=5)
print('主题及其 top5 的单词:\n', topic_words) # * 前的数值表示单词权重
基于 TextRank 的关键词提取
我们知道,图由一系列节点和边构成,在图模型的框架下,文本中的词被当作图的节点,词与词之间的关系便是图的边,根据关联的程度还可以为边施加权重值。比如下图中便表示了词语“股票”与其它词之间的关系,边的上数值还可以表示关系的关联度。
因此抽取关键词的任务便转化成了按照重要性将节点进行排序的过程。对于节点重要性的考量,主要涉及以下方面的因素:
度:节点的度是指和该节点相关联的边的条数,又称关联度,表明了节点的影响能力。特别地,对于有向图,节点的度又分为入度和出度,分别表示指向该节点的边的条数和从该节点出发的边的条数。这就好比越是重要的城市,与周边城市的铁路连接率越高。
接近中心性:每个结点到其它节点最短路径的平均长度。对于一个结点而言,距离其它节点越近,那么它的中心度越高。比如一个城市的中心地带往往出行方便,离各个公共设施都比较近。
中介中心性:指的是一个节点担任其它两个节点之间最短路径中介的次数。一个结点充当“中介”的次数越高,它的中介中心度就越大。比如,在城市地铁交通网络中,一些比较重要的地点往往在很多路线上都会出现。
特征向量:由周围所有连接的节点决定,等于其相邻节点的中心化指标之线性叠加,表示的是通过与具有高度值的相邻节点所获得的间接影响力。有一句俗话是这样的,你所有朋友的平均收入便是你的收入,说的便是同一个道理。
这一系列指标都从不同侧面反映了节点的重要程度,在实际应用中,可以根据具体情况选择或者组合合适的计量方式。另外,除了综合考虑各项指标以外,基于图提取关键词的一大重要算法便是 TextRank,这种算法源自谷歌搜索的核心算法 PageRank,其思想主要为以下几个方面:
如果一个网页被很多其他网页链接到,说明这个网页比较重要,也就是 PageRank 值会相对较高。
如果一个 PageRank 值很高的网页链接到一个其他的网页,那么被链接到的网页的 PageRank 值会相应地因此而提高。
类似地,基于 PageRank 的 TextRank,其核心思想如下:
如果一个单词出现在很多单词后面,说明这个单词比较重要。
一个 TextRank 值很高的单词后面跟着的单词,TextRank 值会相应地因此而提高。
TextRank 不仅可应用于关键词的提取,还可应用于摘要提取,很多工具包都提供了现成的 TextRank 算法。比如 jieba 中也提供了 TextRank,只需要几行代码便能提取出关键词。
keywords = jieba.analyse.textrank(
text, topK=5, withWeight=True, allowPOS=('ns', 'n', 'vn', 'n'))
keywords