>>> from env_helper import info; info()
页面更新时间: 2024-01-15 21:12:55
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-16-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

1.2. jieba结巴分词–关键词抽取(核心词抽取)

1.2.1. 简介

关键词抽取就是从文本里面把跟这篇文档意义最相关的一些词抽取出来。这个可以追溯到文献检索初期,当时还不支持全文搜索的时候,关键词就可以作为搜索这篇论文的词语。因此,目前依然可以在论文中看到关键词这一项。

除了这些,关键词还可以在文本聚类、分类、自动摘要等领域中有着重要的作用。比如在聚类时将关键词相似的几篇文档看成一个团簇,可以大大提高聚类算法的收敛速度;从某天所有的新闻中提取出这些新闻的关键词,就可以大致了解那天发生了什么事情;或者将某段时间内几个人的微博拼成一篇长文本,然后抽取关键词就可以知道他们主要在讨论什么话题。

总之,关键词就是最能够反映出文本主题或者意思的词语。但是网络上写文章的人不会像写论文那样告诉你本文的关键词是什么,这个时候就需要利用计算机自动抽取出关键词,算法的好坏直接决定了后续步骤的效果。

关键词抽取从方法来说大致有两种:

  • 第一种是关键词分配,就是有一个给定的关键词库,然后新来一篇文档,从词库里面找出几个词语作为这篇文档的关键词;

  • 第二种是关键词抽取,就是新来一篇文档,从文档中抽取一些词语作为这篇文档的关键词;

目前大多数领域无关的关键词抽取算法(领域无关算法的意思就是无论什么主题或者领域的文本都可以抽取关键词的算法)和它对应的库都是基于后者的。从逻辑上说,后者比前着在实际使用中更有意义。

从算法的角度来看,关键词抽取算法主要有两类:

  • 有监督学习算法,将关键词抽取过程视为二分类问题,先抽取出候选词,然后对于每个候选词划定标签,要么是关键词,要么不是关键词,然后训练关键词抽取分类器。当新来一篇文档时,抽取出所有的候选词,然后利用训练好的关键词抽取分类器,对各个候选词进行分类,最终将标签为关键词的候选词作为关键词;

  • 无监督学习算法,先抽取出候选词,然后对各个候选词进行打分,然后输出topK个分值最高的候选词作为关键词。根据打分的策略不同,有不同的算法,例如TF-IDF,TextRank等算法;

jieba分词系统中实现了两种关键词抽取算法,分别是基于TF-IDF关键词抽取算法和基于TextRank关键词抽取算法,两类算法均是无监督学习的算法,下面将会通过实例讲解介绍如何使用jieba分词的关键词抽取接口以及通过源码讲解其实现的原理。

1.2.2. 基于TF-IDF算法进行关键词抽取

  • jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())

    • sentence 为待提取的文本

    • topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20

    • withWeight 为是否一并返回关键词权重值,默认值为 False

    • allowPOS 仅包括指定词性的词,默认值为空,即不筛选

  • jieba.analyse.TFIDF(idf_path=None) 新建 TFIDF 实例,idf_path 为 IDF 频率文件

基于TF-IDF算法进行关键词抽取的示例代码如下所示,

>>> import jieba,math
>>> import jieba.analyse
>>> # ’analyse.extract.tags‘
>>> str_text="""线程(英语:thread)是操作系统能够进行运算调度的最小单位。
>>> 它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个
>>> 单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的
>>> 任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),
>>> 但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。
>>> """
>>> keywords1=jieba.analyse.extract_tags(str_text)
>>> print('关键词提取:'+"/".join(keywords1))
>>>
>>> keywords_top=jieba.analyse.extract_tags(str_text,topK=3)
>>> print('关键词topk:'+"/".join(keywords_top))#有时不确定提取多少关键词,可利用总词的百分比
>>>
>>> print('总词数:{}'.format(len(list(jieba.cut(str_text)))))
>>>
>>> total=len(list(jieba.cut(str_text)))
>>>
>>> get_cnt=math.ceil(total*0.1)  #向上取整
>>> print('从%d 中取出%d 个词'% (total,get_cnt))
>>>
>>> keywords_top1=jieba.analyse.extract_tags(str_text,topK=get_cnt)
>>> print('关键词topk:'+"/".join(keywords_top1))
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
Loading model cost 0.766 seconds.
Prefix dict has been built successfully.
关键词提取:线程/进程/thread/轻量/控制流/并行执行/Unix/System/SunOS/lightweight/processes/kernel/user/单位/多指/内核/称为/并发/操作系统/每条
关键词topk:线程/进程/thread
总词数:109
从109 中取出11 个词
关键词topk:线程/进程/thread/轻量/控制流/并行执行/Unix/System/SunOS/lightweight/processes

基于TextRank算法进行关键词抽取

  • jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=(‘ns’, ‘n’, ‘vn’, ‘v’)) 直接使用,接口相同,注意默认过滤词性。

    • sentence:待提取关键词的文本

    • topK:返回关键词的数量,重要性从高到低排序

    • withWeight:是否同时返回每个关键词的权重

    • allowPOS:词性过滤,为空表示不过滤,若提供则仅返回符合词性要求的关键词,allowPOS(‘ns’, ‘n’, ‘vn’, ‘v’) 地名、名词、动名词、动词

  • jieba.analyse.TextRank() 新建自定义 TextRank 实例

基本思想:

  1. 将待抽取关键词的文本进行分词

  2. 以固定窗口大小(默认为5,通过span属性调整),词之间的共现关系,构建图

  3. 计算图中节点的PageRank,注意是无向带权图

基于TextRank算法进行关键词抽取的示例代码如下所示,

>>> import jieba
>>>
>>>
>>> #原始文本
>>> text="""线程(英语:thread)是操作系统能够进行运算调度的最小单位。
>>> 它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个
>>> 单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的
>>> 任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),
>>> 但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。
>>> """

引入TextRank关键词抽取接口:

>>> for x, w in jieba.analyse.textrank(str_text, withWeight=True):
>>>     print('%s %s' % (x, w))
进程 1.0
线程 0.7470505535857219
单位 0.38800337922730044
运算 0.34027047401967436
调度 0.33931684198043416
轻量 0.31102185714719194
运作 0.30959463951292987
进行 0.26874515685837774
能够 0.2660654985282964
实际 0.24067886508987982
控制流 0.23990311306688275
称为 0.236108598329124
内核 0.236108598329124
并发 0.16886282860541446
顺序 0.14763535550073484
包含 0.10572734204245057
用户 0.10390537624323205
>>> !jt
/bin/bash: line 1: jt: command not found