文章目录

  • Part1前言
  • Part2实现工具——jieba
  • Part3TF-IDF 算法
  • 1算法原理
  • 2代码实现
  • 3优缺点分析
  • Part4TextRank 算法
  • 1算法思想
  • 2代码实现
  • 3优缺点概述
  • Part5结束语
  • 题外话

Part1前言

自然语言处理中最基本的任务就是文本词频统计和关键词提取,在过去的文章中,我们已经详细介绍了使用 Python 对文本进行词频统计的方法,通过统计词频,我们可以大致了解文章构成,并且在一定程度上了解文章的重点内容。而文本关键词提取工作则可以让我们更加直观地了解文章的主题思想,也可以用来做一些情感分析、内容摘要、文本分类聚类等文本分析工作,这也是很多学者关心的问题。关键词提取技术中有很多优异算法,本文我们将介绍如何使用 Python 基于 TF-IDF 和 TextRank 这两种算法实现中文长文本(文章)的关键词提取。

Part2实现工具——jieba

Python 第三方库 jieba 是一个开源的,用于中文分词以及简单文本处理的工具包,不仅提供了基础的分词功能,还附带词性标注、实体识别以及关键词提取功能。基本的分词功能以及优化分词的方法,已经在上文链接指向的文章中详细说明过,本文则主要介绍如何使用 jieba 库进行关键词提取。jieba 库内置了两种关键词提取算法,正是上文中提到的 TF-IDF 和 TextRank 算法,它们都是最为经典和常用的关键词提取算法。

当然,除了 jieba 库,Python 中很多自然语言处理相关的第三方库也提供了关键词提取功能,例如 hanlp、Scikit-learn 等,但相对而言 jieba 的使用更加简单,易上手,因此本文主要使用的工具是 jieba,不过后续文章也有可能介绍其他更强的工具库。

Part3TF-IDF 算法

1算法原理

TF-IDF(Term Frequency–Inverse Document Frequency,词频-逆文档频率)是信息检索中衡量一个词语重要程度的统计指标,广泛应用于文本分析领域。

我们知道,通过对一个文档进行分词并统计词频,可以知道文档中出现频率最高的一些词语,进而得知文档中重要的词汇。不过这种方法存在一个缺陷,那就是分词后一些助词或副词的出现频率极高,例如“的”、“非常”以及一些标点符号。虽然可以通过去除停用词来剔除一部分标点符号和非重要词语,但这种方法治标不治本,泛化性不够。不过只要我们对词频增加一个惩罚项就可以极大程度地剔除高频但不重要的词语,仅保留重要词语,也就是文档的关键词。那么这个惩罚项是怎样的呢?打个比方,副词“非常”在一个文档 A 中的出现频率非常高,但是这个词在其他文档中出现的频率也很高,达到了 80%,也就是说如果有 100 份文档,那么其中 80 份文档中都含有这个词语,那就说明该词语是一个很普遍的词,作为文档 A 关键词的可能性就很低。反之,如果词语“经济”在文档 A 中频繁出现,但是在其他文档中出现频率不高,那么就认为这个词语是关键词的可能性更大。实际上这就是 TF-IDF 算法的原理,TF 指的就是一个词语的词频,只不过需要需要先除以文档中的总词数,防止 TF 值更加偏向于长文本中的词语,而 IDF 是这个词语在所有文档中出现的频率,然后取对数,就得到这个词语的 IDF 值。最后,TF 值与 IDF 值相乘就得到了这个词语的 TF-IDF 值,即词语的重要程度,算法公式如下。

根据公式可知,TF-IDF 算法需要依赖大量的文本,只有这样才能更加准确地计算词语的逆文档频率(IDF 值)。也就是说提取一篇文章的关键词,需要用到成百上千篇其他不同的文章,这使得该算法的实现相当不容易,所以 jieba 库的开发者使用了大量的文本(据说是人民日报)作为语料事先训练得到四十多万个词语的 IDF 值,并将他们保存在 jieba 库的文件中,如下图所示。

python只提取部分文本 python提取文本信息_Python学习

这样一来,使用 jieba 库提取文本关键词只需要提供要提取关键词的文档就可以了。

2代码实现

如果你还没有安装 jieba 库,那么首先需要在 Python 中安装它

pip install jieba

GitHub 地址:https://github.com/fxsjy/jieba

下面是使用 jieba 提取新闻《人民热评:“鲶鱼”终于带出大鱼,潜伏再深也难逃捕捞!》中前 10 关键词的代码。

python只提取部分文本 python提取文本信息_开发语言_02

import jieba.analyse      # 从文本文件中读取文本内容,并作简单清洗   with open('新闻文本.txt', 'r', encoding='utf-8') as file:       # 去除换行符,使文本连续       TEXT = file.read().replace('\n', '')      # 使用 jieba 进行 TF-IDF 算法提取文本关键词   keywords = jieba.analyse.extract_tags(       sentence=TEXT,    # 文本内容       topK=10,          # 提取的关键词数量       allowPOS=['n','nz','v', 'vd', 'vn', 'ns', 'nr'],  # 允许的关键词的词性       withWeight=True,  # 是否附带词语权重       withFlag=True,    # 是否附带词语词性   )   # 输出提取到的关键词   keywords      # 输出内容如下   """   [(pair('钟庚赐', 'nr'), 0.564398728854661),    (pair('鲶鱼', 'n'), 0.5130897535042374),    (pair('北极', 'ns'), 0.41047180280338985),    (pair('大鱼', 'n'), 0.2565448767521187),    (pair('事件', 'n'), 0.2565448767521187),    (pair('退休', 'v'), 0.2565448767521187),    (pair('通报', 'n'), 0.20523590140169493),    (pair('违法', 'vn'), 0.20523590140169493),    (pair('问题', 'n'), 0.20523590140169493),    (pair('违规', 'vn'), 0.20523590140169493)]   """

在 jieba 中,使用jieba.analyse.extract_tags()函数就可以基于 TF-IDF 算法提取文章的关键词,其中参数allowPOS的作用是限制关键词的词性,jieba 分词常见词性的对照可以参考下图。

python只提取部分文本 python提取文本信息_Python编程_03

3优缺点分析

通过上述代码可以发现,使用 jieba 库基于 TF-IDF 算法的关键词提取,其效果算不上优秀,但也不是很差,与人工提取还有一定差异,毕竟这项工作本身就是一个见仁见智的问题。

**先说缺点,**提取效果一般,一些特殊场景下的专有词汇或者新词汇没有被提取出来,例如“北极鲶鱼”显然可以作为一个关键词,但由于 jieba 的词库中没有这个词,因此“北极鲶鱼”被分词器分开为“北极”和“鲶鱼”,所以尽管“北极鲶鱼”多次出现,关键词也只能是“北极”和“鲶鱼”。这个特性导致该工具只在一部分文本的关键词提取中表现良好,对于特定领域的文本处理则相对平庸。另外,jieba 库 0.42.1 版本自 2020 年发布,到现在已经有三年多没有更新,内置的各种词库也随着时间推进越来越落后。

**再说优点,**上述算法/代码最大的优点就是实现起来非常简单,几乎没有什么难度,非常亲民,即便没有大量文本做支撑,也可以方便的实现 TF-IDF 算法,而且还可以限制关键词的词性,并且给出各个关键词的权重。如果你有更高的要求,那么就需要根据算法原理手搓代码了,这一步还涉及到词库的开发、文本语料库的选择与处理等等,比现有代码复杂许多,这里就不深入讨论了。

Part4TextRank 算法

1算法思想

TextRank 算法的前身是 Google 用于网页排序的 PageRank 算法。它将互联网看作有向图,互联网上的网页看作节点,一个网页可能被其他网页链接,也可能链接其他网页。当一个网页经常被其他网页链接,那么有理由认为这个网页比较重要,但一个网页的每一个外链(每一次被链接)并不是同等重要。正所谓物以类聚,如果一个网页频繁被垃圾网站链接,那么这个网页往往也是垃圾网站,但如果一个网站被另一个重要的网站链接,则说明这个网站也很重要。而且外链的权重也与外链的数量有关系,例如一个网页连接了很多其他网页,那么每一个链接的权重都不会高,如果只链接一个网页,这个链接的权重就会提高不少。PageRank 给每一个网页赋予同样的初始权重,然后以迭代的方式更新每一个网页的权重,直到所有网页的权重值都不再变化,那么就能给这些网页做出重要性排序了。

而 TextRank 算法其实就是 PageRank 算法在文本上的应用。首先,将要处理的文本进行分词,把所有的单词作为候选关键词。然后,根据单词之间的某种关系,例如共现关系,构建一张图,图中的节点表示候选关键词,边表示这两个词之间的关系。在图上运行 TextRank 算法,进行迭代,直到达到稳定的状态。最后,每个节点(单词)都会被赋予一个权重,权重越高,该单词作为关键词的可能性越大。

python只提取部分文本 python提取文本信息_python只提取部分文本_04

图源网络,侵删

2代码实现

jieba 库同样也内置了 TextRank 算法来提取关键词,下面我们依旧以上文中的新闻文本为例,使用 TextRank 提取排名前十的关键词。

import jieba.analyse      # 从文本文件中读取文本内容,并作简单清洗   with open('新闻文本.txt', 'r', encoding='utf-8') as file:       # 去除换行符,使文本连续       TEXT = file.read().replace('\n', '')      # 使用 jieba 进行 TF-IDF 算法提取文本关键词   keywords = jieba.analyse.textrank(       sentence=TEXT,    # 文本内容       topK=10,          # 提取的关键词数量       allowPOS=['n','nz','v', 'vd', 'vn', 'ns', 'nr'],  # 允许的关键词的词性       withWeight=True,  # 是否附带词语权重       withFlag=True,    # 是否附带词语词性   )   # 输出提取到的关键词   keywords      # 输出内容如下   """   [(pair('钟庚赐', 'nr'), 1.0),    (pair('鲶鱼', 'n'), 0.7769707000291773),    (pair('北极', 'ns'), 0.6686246005812482),    (pair('事件', 'n'), 0.5126830875120408),    (pair('违法', 'vn'), 0.44885458849077187),    (pair('通报', 'n'), 0.4358104933456967),    (pair('违规', 'vn'), 0.3890063023078582),    (pair('应该', 'v'), 0.3501519458778275),    (pair('退休', 'v'), 0.32187418179123195),    (pair('部门', 'n'), 0.31891706852131835)]   """

从提取结果来看,该算法和 TF-IDF 算法都还算可以。

3优缺点概述

由于 TextRank 算法从原理上来说不需要依赖其他文本集合,仅需一篇文章就可以完成解析,所以相比于 TF-IDF 算法,它在任何主题的文本中的表现应该都不会很差,这一点优于 TF-IDF。不足之处在于算法原理比较抽象,即便想根据原理手写代码也会发现比较困难,不过好在现在这些算法都可以被直接调用,没有什么开发成本。

Part5结束语

python只提取部分文本 python提取文本信息_Python学习_05