基于语义的统计语言模型实现关键词抽取

管理员账号

2017-11-30

小编说:关键词提取能让我们快速地了解一篇文章。在信息爆炸的时代,能够有效提取文本的关键词,对于快速、及时、高效地获取信息是非常有帮助的。本文介绍一种能够体现文本语义关系的关键词提取算法。本文选自《自然语言处理技术入门与实战》一书。

场景

对于如下的文本,如何提取出更加符合其主题分布的关键词。

1.鲜花多少钱?

2.白百合多少钱?

3.水仙花多少钱?

上面这三个语句,描述的都是鲜花这个主题下面的问题。所以如果希望提取的关键词更加符合其主题分布,那么应该是“鲜花”的权重最高。如果按照TF-IDF、TextRank的算法(更多反映的是文本的统计信息的算法),“鲜花”、“白百合”、“水仙花”这三个词的权重是一样的(当然如果你认为“多少钱”应该是这三个语句的主题,那么这三个词的权重一致也就是理所当然的了)。针对这种情况,我们介绍一种基于LDA(Latent Dirichlet Allocation)的关键词提取算法。

LDA模型包含词、主题和文档三层结构,如图1所示。LDA最早是由Blei等,以pLSI为基础,提出的服从Dirichlet分布的K维隐含随机变量表示文档主题概率分布、模拟文档的一个产生过程。后来Griffiths等对参数β施加了Dirichlet先验分布,使得LDA模型成为一个完整的生成模型。

图1 LDA的图模型

其中,

1.φk为主题k中的词汇概率分布,θm为第m篇文档的主题概率分布,φk和θm服从Dirichlet分布,φk和θm作为多项式分布的参数分别用于生成主题和单词。

2.α和β分别为φk和θm的分布参数,α反映了文档集中隐含主题之间的相对强弱,β为所有隐含主题自身的概率分布。

3.K为主题数目。

4.M为文档集中文档的数目。

5.Nm为第m篇文档的词的总数。

6.ωm,n和Zm,n分别为第m篇文档中第n个单词和其隐含主题。

原理

如上所述,在LDA模型中,包含词、主题、文档三层结构。该模型认为一篇文档的生成过程是:先挑选若干主题,再为每个主题挑选若干词语。最终,这些词语就组成了一篇文章。所以主题对于文章是服从多项分布的,同时单词对于主题也是服从多项分布的。基于这样的理论,我们可以知道,如果一个单词w对于主题t非常重要,而主题t对于文章d又非常重要,那么单词w对于文章d就很重要,并且在同主题的词Wi(i=1,2,3,…)里面,单词w的权重也会比较大。而这正好可以解决我们上面所描述的问题。

所以下面就要计算两个概率:单词对于主题的概率和主题对于文档的概率。这里我们选择Gibbs采样法来进行概率的计算。具体公式如下:

主题Tk下各个词Wi的权重计算公式:

【公式1】P(wi│T_k )=(C_ik+β)/(∑(i=1)^N▒C_ik +N*β)=φ_i^(t=k)

其中

Wi:表示单词集合中任一单词。

Tk:表示主题集合中任一主题。

P(wi│Tk ):表示在主题为k时,单词i出现的概率,其简记的形式为φi^(t=k)。

Cik:表示语料库中单词i被赋予主题k的次数。

N:表示词汇表的大小。

β:表示超参数。

文档D_m下各个词T_k的权重计算公式:

【公式2】P(Tk│D_m )=(C_km+α)/(∑(k=1)^K▒Ckm +K*α)=θ(t=k)^m

其中

Dm:表示文档集合中任一文档。

Tk:表示主题集合中任一主题。

P(Tk丨Dm):表示在文档为m时,主题k出现的概率,其简记的形式为θt=k^m。

Ckm:表示语料库中文档m中单词被赋予主题k的次数。

K:表示主题的数量。

α:表示超参数。

在上述两个公式中,为了平滑非包含的单词和主题,所以分子中分别添加了LDA模型中的超参数α和β。如果觉得所计算的场景不需要,也可以不加这两个参数。

现在得到了指定文档下某主题出现的概率,以及指定主题下、某单词出现的概率。那么由联合概率分布可以知道,对于指定文档某单词出现的概率可以由如下公式计算得到:

【公式3】P(wi│D_m )=∑(k=1)^K▒〖φi^(t=k)*〗 θ(t=k)^m

基于上述公式,我们就可以算出单词i对于文档m的主题重要性。但是由于在LDA主题概率模型中,所有的词汇都会以一定的概率出现在每个主题,所以这样会导致最终计算的单词对于文档的主题重要性值区分度受影响。为了避免这种情况,一般会将单词相对于主题概率小于一定阈值的概率置为0。至于这个阈值设置为多少,则可以根据自己的实际情况自由选择。

实例

基于本文开头提出的场景,我们来完成基于文章主题权重的关键词提取实例。同上面所述,分词在这里不是重点,所以分词部分就不做特别说明了。假设我们对上述一句话完成了分词,并且将各个词按照空格分隔存储在了一起。

首先处理掉非重要词,采用正向过滤的方法,即选择特定词性的词,在这里我们选择词性为名词、形容词等词性的词。

在得到候选词表后,对语料库进行Gibbs采样,得到单词-主题,文档-主题的分布统计矩阵。

计算单词对于文档的主题概率权重的实现代码如下所示:

for (int j = 0; j < strArray.length; j++) {
String word = strArray[j];//获得当前要计算的单词
int i = wordIndexMap.get(word);//获得给定单词在单词-主题分布矩阵中的行号
//计算单词在指定文档m中的主题概率权重
double word2TopicWeightSum = 0.0;
//遍历所有主题,计算其对于单词i的频次总和
for (int k = 0; k < topicSize; k++) {
  word2TopicWeightSum += word2TopicCount[i][k];
}
double topic2DocWeightSum = 0.0;
//遍历所有主题,计算其对于文档m的频次总和
for (int k = 0; k < topicSize; k++) {
  topic2DocWeightSum += topic2DocCount[m][k];
}
double weightSum = 0.0;
//遍历所有主题,计算其单词i对于文档m的主题概率权重
for (int k = 0; k < topicSize; k++) {
  double word2TopicWeight = (word2TopicCount[i][k] + beta)/(word2TopicWeightSum + wordSize*beta);
  double topic2DocWeight = (topic2DocCount[m][k] + alpha)/(topic2DocWeightSum + topicSize*alpha);
  weightSum += word2TopicWeight*topic2DocWeight;
}
resultMap.put(word, weightSum);
    }

这里以一个文档文本的处理为例,多个文档则在外面再多加一层循环即可。首先对输入文本按照空格进行切分,获得每一个单词,然后统计每个词的主题概率权重。其中代码部分为第1~20行。

1.因为对于每一个单词,在计算其相对于文档m的主题概率权重的时候,文档m都是确定的,所以在遍历每个单词之前先要对主题-文档的分布概率求和,计算其总的频次数,以备后续计算使用。如代码第1~4行所示。

2.对于要计算的单词,首先要获得它在单词-文档的分布矩阵中的位置,也即双数组存储的行号。这里需要说明一点,因为我们待计算的文档,也会放到语料库中进行学习,所以不会存在待计算的单词不在已知单词库中的情况。对于因为主题概率分布太小而被过滤掉的单词,它的计数会被置为0,而这一单元格的记录还是被保留的,所以这里不会出现空指针的问题。

3.因为主题数量一般不会太大,所以就先进行了主题的遍历,求出指定单词相对于各个主题分布词频数的总和,以备后续计算使用。如代码第11~13行所示。

4.最终我们将计算结果存储在一个map中,以备后续计算排序筛选,具体计算方式见《自然语言处理技术入门与实践》一书。

拓展

从上可以看出,基于LDA主题概率模型的关键词提取方法的准确度,会严重依赖于基础语料库,而这个语料库还需要有一定的丰富性,这样才可以使得计算的概率值具有一定的鲁棒性。这就会造成比较大的人力投入,对于模型的灵活扩展就会受到限制。

基于本框架本身的改进并不是很多,而借助于其他方法,对于上述缺陷的改进的方法还是比较多的,比如通过借助于知网,或者同义词林的方法获得单词的准确语义关系,这样就可以获得更好的语义关系。同时基于这些准确的语义关系,可以建立词语结构模板;然后基于这些模板运用频繁模式挖掘,发掘更多的符合这样词语结构模板的词语关系;并且根据预先设置的规则条件,给这些词语对添加对应的语义关系;这样就可以实现语义的批量扩展,增大基础的语料数据。

读者评论

相关专题

相关博文

  • 专访丨一学就会的自然语言处理系统书

    专访丨一学就会的自然语言处理系统书

    管理员账号 2017-12-26

    《自然语言处理技术入门与实战》 手把手教你搭建自然语言处理系统! 实用技术要点,完整解决方案 兰红云 编著 2017年11月出版 一本一学就会的自然语言处理系统书 避免繁琐和突兀的数学证明 没有复杂公式,也...

    管理员账号 2017-12-26
    535 0 0 0