基于统计方法的核心思想就是计算文本中每个term的分值,有了分值,就可以对所有的term进行排序,然后获取top n个分值最大的term作为文本的关键词。不同的统计方法计算每个term的分值方式不同。
Term-Frequency(TF)词频是最简单的一种方法,通过词在文档里出现的频率进行分值计算。虽然方法简单,却是一种很有效的方法获取文档中的重要主题topics。每个term的分值计算如下:
t f w o r d = N w o r d N a l l tf_{word} = \frac{N_{word}}{N_{all}} tfword=NallNword
其中, N w o r d N_{word} Nword表示该词在文本中出现的次数, N a l l N_{all} Nall表示整个文本的单词频率数。
基于词频的主要问题在于,没有考虑结构化和语义信息,同时也不能区分同义词,而且有些停用词在所有文档出现的频率都很高。
TF-IDF是一种很简单但却很有效的方法,计算文本中的每个term会考虑两个因素。一是term本身在文档中的词频,这就是上小结提到的TF,另一个是倒文本频率(Inverse Document Frequency)IDF,这个指标衡量的是有多少文本包含了该term。IDF主要用来惩罚那些在很多文本中都有出现的term,往往这些term都是一些无关紧要的停用词等。
TF-IDF的数学公式如下:
t f i d f w o r d = t f w o r d ∗ l o g ( D D w o r d ) tfidf_{word} = tf_{word} * log(\frac{D}{D_{word}}) tfidfword=tfword∗log(DwordD)
其中 D D D表示整个文档的数量。 D w o r d D_{word} Dword表示包含该word的文档数量,从公式可以看出, D w o r d D_{word} Dword越大,整个分值就越小。tfidf整个核心思想就是,term在一个文档的重要程度取决于该term在该文档的频率和在其它文档的出现的次数。
A Text Feature Based Automatic Keyword
Extraction Method for Single Documents
YAKE(Yet Another Keyword Extractor)是一种无监督的关键词提取算法,特征提取主要考虑五个因素(去除停用词后):
S ( t ) S(t) S(t)表示的是单词 t t t的分值情况,其中 s ( t ) s(t) s(t)分值越小,表示的单词 t t t越重要。
在介绍TextRank之前,让我们先来回顾下PageRank,假设有如下图:
计算每个节点的公式如下:
S ( V i ) = ( 1 − α ) ∣ V ∣ + α ∗ ∑ V j ∈ I n ( V i ) 1 ∣ O u t ( V j ) ∣ S ( V j ) S(V_i) = \frac{(1-\alpha)}{|V|} + \alpha* \sum_{V_j \in In(V _i)} \frac{1}{\begin{vmatrix}Out(V_j)\end{vmatrix}}S(V_j) S(Vi)=∣V∣(1−α)+α∗Vj∈In(Vi)∑∣ ∣Out(Vj)∣ ∣1S(Vj)
其中 S ( V i ) S(V_i) S(Vi)表示网页 i i i的权重分值, I n ( V i ) In(V_i) In(Vi)表示指向节点 V i V_i Vi的节点, O u t ( V j ) Out(V_j) Out(Vj)表示节点 V j V_j Vj指出的节点。 ∣ O u t ( V j ) ∣ \begin{vmatrix}Out(V_j)\end{vmatrix} ∣ ∣Out(Vj)∣ ∣表示节点 V j V_j Vj指出节点的总数。为了保证PageRank(或者随机游走)不会死循环到一个环出不来,增加了一个随机因子 α \alpha α, α \alpha α表示不进行随机跳转的概率。让我们看看,上图节点 e e e的权重分值计算过程。
首先我们可以用一个矩阵表示图中节点 a , b , e , f a, b, e, f a,b,e,f的连接关系:
a | b | e | f | |
---|---|---|---|---|
a | 0 | 0 | 0 | 0 |
b | 0 | 0 | 0 | 0 |
e | 1 | 1 | 0 | 0 |
f | 0 | 1 | 0 | 0 |
每一行代表该指向该节点的节点,每一列代表该节点指向其它的节点。根据上面的公式 1 ∣ O u t ( V i ) ∣ \frac{1}{\begin{vmatrix}Out(V_i)\end{vmatrix}} ∣Out(Vi)∣1,需要对每一列进行归一化,所以调整如下:
a | b | e | f | |
---|---|---|---|---|
a | 0 | 0 | 0 | 0 |
b | 0 | 0 | 0 | 0 |
e | 1 | 0.5 | 0 | 0 |
f | 0 | 0.5 | 0 | 0 |
然后我们用这个矩阵去乘以每个节点的权重,最开始,每个节点的权重初始化都为1,如下计算:
[ 0 0 0 0 0 0 0 0 1 0.5 0 0 0 0.5 0 0 ] ∗ [ 1 1 1 1 ] = [ 0 0 1.5 0.5 ] \begin{bmatrix}0 &0 &0 &0\\ 0 & 0 & 0 &0 \\ 1& 0.5 & 0 &0\\0& 0.5 & 0 &0\end{bmatrix} * \begin{bmatrix} 1 \\ 1 \\1 \\1 \end{bmatrix} = \begin{bmatrix} 0 \\0 \\ 1.5 \\ 0.5 \end{bmatrix} ⎣ ⎡0010000.50.500000000⎦ ⎤∗⎣ ⎡1111⎦ ⎤=⎣ ⎡001.50.5⎦ ⎤
这只是一次迭代,加入衰减因子 α \alpha α,python迭代多次结果如下:
# -*-coding:utf8 -*-
import sys
import numpy as np
def pagerank(graph):
'''
简单实现pagerank迭代过程
'''
pr = np.array([1, 1, 1, 1]) #init node
a = 0.85
for iter in range(10):
pr = (1-d) + d * np.dot(graph, pr)
print(iter)
print(pr)
if __name__=='__main__':
graph = np.array([[0,0,0,0],
[0,0,0,0],
[1, 0.5, 0, 0],
[0,0.5,0,0]])
pagerank(graph)
output:
最后节点 e e e的PageRank分值为0.34125。
TextRank: Bringing Order into Texts
TextRank算法是基于PageRank算法,PageRank算法,其中图的节点是网页,而TextRank是词。
最原始的PageRank算法是无权重的图,而TextRank是有权重的图。因此,节点的权重分值计算和PageRank比变动如下:
W S ( V i ) = ( 1 − α ) ∣ V ∣ + α ∗ ∑ V j ∈ I n ( V i ) w j i ∑ v k ∈ O u t ( V j ) w j k W S ( V j ) WS(V_i) = \frac{(1-\alpha)}{|V|} + \alpha* \sum_{V_j \in In(V_i)} \frac{w_{ji}} {\sum_{v_k \in Out(V_j) }w_{jk}} WS(V_j) WS(Vi)=∣V∣(1−α)+α∗Vj∈In(Vi)∑∑vk∈Out(Vj)wjkwjiWS(Vj)
其中 w i j w_{ij} wij表示了节点 V j V_j Vj与节点 V j V_j Vj之间的边连接权重。
接下来看TextRank算法的步骤流程:
CollabRank: Towards a Collaborative Approach to Single-Document Keyphrase Extraction
SingleRank是PageRank的变体,主要有两个变化:
TopicRank: Graph-Based Topic Ranking for Keyphrase Extraction
TopicRank把主题当做相似关键短语的簇,这些topics会根据在文档的重要性进行排序,然后选取top 个最相关的topics,每个topic选择一个最重要的关键短语来代表文档的核心关键词。
TopicRank算法的步骤如下:
PositionRank: An Unsupervised Approach to Keyphrase Extraction from Scholarly Documents
PositionRank也是一种基于图结构的算法,根据词的位置和词频来计算每个词的分值。算法主要三个部分组成:
为了保证PageRank(或者随机游走)不会死循环到一个环出不来,一个衰减因子 a a a允许跳入到任何一个节点中去。所以迭代更新公式如下:
S = a . M ~ . S + ( 1 − a ) . p ~ S = a. \tilde M. S + (1-a).\tilde p S=a.M~.S+(1−a).p~
其中 p ~ \tilde p p~是一个长度为 ∣ V ∣ \begin{vmatrix} V \end{vmatrix} ∣ ∣V∣ ∣,每个元素值为 1 ∣ V ∣ \frac{1}{\begin{vmatrix} V \end{vmatrix}} ∣V∣1的向量。
Position-Biased PageRank会根据每个词的位置的导数计算权重,若一个词出现在文档多个位置,则分值相加。核心思想是:越在一个文档靠前的位置,权重越大,同时频率出现越高,权重也越大。
假设一个词在文档的位置时第二,第五,第10,则权重分值为:1/2+1/5+1/10=0.8。再进行归一化,则向量 p ~ \tilde p p~的计算公式如下:
p ~ = [ p 1 p 1 + p 2 + . . . + p ∣ V ∣ , p 2 p 1 + p 2 + . . . + p ∣ V ∣ , . . . , p v p 1 + p 2 + . . . + p ∣ V ∣ ] \tilde p = \begin{bmatrix} \frac{p_1}{p_1+p_2+...+p_{\begin{vmatrix} V\end{vmatrix}}} , \frac{p_2}{p_1+p_2+...+p_{\begin{vmatrix} V\end{vmatrix}}} , ...,\frac{p_v}{p_1+p_2+...+p_{\begin{vmatrix} V\end{vmatrix}}} \end{bmatrix} p~=[p1+p2+...+p∣V∣p1,p1+p2+...+p∣V∣p2,...,p1+p2+...+p∣V∣pv]
最后迭代计算公式如下:
S ( v i ) = ( 1 − a ) . p i ~ + a . ∑ v j ∈ A d j ( v i ) w j i O ( v j ) S ( v j ) S(v_i) = (1-a). \tilde{p_i} +a . \sum_{v_j \in Adj(v_i)} \frac{w_{ji}}{O(v_j)} S(v_j) S(vi)=(1−a).pi~+a.vj∈Adj(vi)∑O(vj)wjiS(vj)
其中 O ( v j ) = ∑ v k ∈ A d j ( v j ) w j k O(v_j) = \sum_{v_k \in Adj(v_j)}w_{jk} O(vj)=∑vk∈Adj(vj)wjk, p i ~ \tilde{p_i} pi~是向量 p ~ \tilde p p~节点为 v i v_i vi的权重。
当相邻两次迭代差异很小,或者迭代达到一个最大迭代次数时,则停止迭代。
基于语义模型的关键词或者短语提取,一般是有监督学习,把关键词提取当做一个标注任务,判断该词是关键词还是不是关键词;或者通过对文本进行分类,基于attention层自动学习文本中的每个词的权重分值,根据分值高低提取关键词。这些方法都是有监督学习,训练模型需要有标签的数据。
更多关于关键词,term weight分值计算,可以参考我的另外一篇blog: 词权重 (term weight) 方法总结
附上一个关键词提取Tools:The 6 Best Keyword Extraction Tools & How to Use Them