前言

关键词提取是从简明概括长文本内容的文档中,自动提取一组代表性短语。关键词是一个简短的短语(通常是一到三个单词),高度概括了文档的关键思想并反映一个文档的内容,清晰反映讨论的主题并提供其内容的摘要。

关键字/短语提取过程包括以下步骤:

  • 预处理: 文档处理以消除噪音。
  • 形成候选tokens:形成 n-gram tokens作为候选关键字。
  • 关键字加权:使用向量器 TFIDF 计算每个 n-gram token (关键短语) 的 TFIDF 权重。
  • 排序: 根据 TFIDF 权重对候选词进行降序排列。
  • 选择前 N 个关键字。

词频逆文档频率(TFIDF)

TFIDF 的工作原理是按比例增加一个词语在文档中出现的次数,但会被它所在的文档数量抵消。因此,诸如“这个”、“是”等在所有文档中普遍出现的词没有被赋予很高的权重。但是,在少数文档中出现太多次的单词将被赋予更高的权重排名,因为它很可能是指示文档的上下文。

Term Frequency

Term Frequency --> 词频

词频定义为单词 (i) 在文档 (j) 中出现的次数除以文档中的总单词数。

Inverse Document Frequency

Inverse Document Frequency --> 逆文档频率

逆文档频率是指文档总数除以包含该单词的文档数的对数。添加对数是为了抑制非常高的 IDF 值的重要性。

TFIDF

TFIDF是通过将词频乘以逆文档频率来计算的。

Python 中的 TFIDF

我们可以使用 sklearn 库轻松执行 TFIDF 向量化。

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(corpus)
print(X.toarray())

Python 库准备

import spacy
import nltk
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
import regex as re
import string
import pandas as pd
import numpy as np
import nltk.data
import re
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('wordnet')
nltk.download('averaged_perceptron_tagger')
from nltk.stem import WordNetLemmatizer
from nltk import word_tokenize, sent_tokenize, pos_tag

[nltk_data] Downloading package stopwords to /root/nltk_data...
[nltk_data]   Package stopwords is already up-to-date!
[nltk_data] Downloading package wordnet to /root/nltk_data...
[nltk_data]   Package wordnet is already up-to-date!
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data]   Package punkt is already up-to-date!
[nltk_data] Downloading package averaged_perceptron_tagger to
[nltk_data]     /root/nltk_data...
[nltk_data]   Package averaged_perceptron_tagger is already up-to-
[nltk_data]       date!

主要使用的是nltk库,如果你没有使用过该库,除了需要pip install nltk,另外还要下载诸如停用词等。或者直接到官网上把整个nltk_data下载下来。

准备数据集

将使用 Theses100 标准数据集[1]来评估关键字提取方法。这 100 个数据集由新西兰怀卡托大学的 100 篇完整的硕士和博士论文组成。这里使用一个只包含 99 个文件的版本。删除其余不包含关键字打文件。论文主题非常多样化:从化学、计算机科学和经济学到心理学、哲学、历史等。每个文档的平均重要关键字数约为 7.67。

你可以将所需的数据集下载到本地。本文已经假设你电脑本地已经存在该数据文件。将编写一个函数来检索文档及其关键字并将输出存储为数据框。

为了演示,我们只选择了其中20个文档。

import os        
path = "./data/theses100/"     
all_files = os.listdir(path   "docsutf8") 
all_keys = os.listdir(path   "keys") 
print(len(all_files)," files n",all_files,
      "n", all_keys) # 不一定要排序

all_documents =[] 
all_keys = [] 
all_files_names = [] 
for i, fname in enumerate(all_files): 
  with open(path 'docsutf8/' fname) as f: 
      lines = f.readlines() 
  key_name= fname[:-4 ] 
  with open(path 'keys/' key_name '.key') as f: 
      k = f.readlines() 
  all_text = ' '.join(lines) 
  keyss = ' '.join(k) 
  all_documents.append(all_text) 
  all_keys.append(keyss.split("n")) 
  all_files_names.append(key_name)
  
import pandas as pd
dtf = pd.DataFrame({'goldkeys': all_keys,
                    'text': all_documents})
dtf.head()

文本预处理

预处理包括标记化、词形还原、小写转换、去除数字、去除空格、去除短于三个字母的单词、去除停用词、去除符号和标点符号。实现这些功能的函数定义为preprocess_text,我附在文末,按需查看。

对于词形还原, 使用了 WordNetLemmatizer 它不会改变单词的词根。

dtf['cleaned_text'] = dtf.text.apply(lambda x: ' '.join(preprocess_text(x)))
dtf.head()

之后,清理每个文档的 goldkeys 并执行词形还原,以便稍后与TFIDF使用Python算法生成的单词进行匹配。

# 清理基本关键字,删除空格和噪音
def clean_orginal_kw(orginal_kw):
  orginal_kw_clean =[]
  for doc_kw in orginal_kw:
    temp =[]
    for t in doc_kw:
      tt = ' '.join(preprocess_text(t))
      if len(tt.split())>0:
        temp.append(tt)
    orginal_kw_clean.append(temp)
  return orginal_kw_clean

orginal_kw= clean_orginal_kw(dtf['goldkeys'])
orginal_kw[0:1]

TFIDF关键词提取

1.生成 n-gram 并对其进行加权

首先,从文本特征提取包中导入 Tfidf Vectorizer

其次,设置参数 use_idf=True ,即希望将逆文档频率 IDF 与词频一起使用。它的最大值是 max_df = 0.5,这意味着我们只想要出现在 50% 的文档中的词条(本文中,对应 99 个中的 49 个文档)。如果一个词语在超过 50 个文档中均出现过,它将被删除,因为它在语料库级别被认为是无歧视性的。指定n-gram的范围从1到3(可以设置更大的数字,但是根据当前数据集的统计,最大的比例是1-3长度的关键字)

然后生成文档的向量。

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(use_idf=True, 
                             max_df=0.5, min_df=1, 
                             ngram_range=(1,3))
vectors = vectorizer.fit_transform(dtf['cleaned_text'])

再者,对于每个文档,均需要构建一个字典( dict_of_tokens ,其中是单词,是 TFIDF 权重。创建一个tfidf_vectors列表来存储所有文档的字典。

dict_of_tokens={i[1]:i[0] for i in vectorizer.vocabulary_.items()}

tfidf_vectors = []  # all deoc vectors by tfidf
for row in vectors:
    tfidf_vectors.append({dict_of_tokens[column]:value for
                          (column,value) in 
                          zip(row.indices,row.data)})

看看这个字典包含的第一个文档

print("The number of document vectors = ", len(tfidf_vectors) , 
      "\nThe dictionary of document[0] :", tfidf_vectors[0])

第一个文档的字典内容

字典的数量与文档的数量相同,第一个文档的字典包含每个 n-gram 及其 TFIDF 权重。

2. 按 TFIDF 权重对关键短语进行排序

下一步是简单地根据 TFIDF 权重对每个字典中的 n-gram 进行降序排序。设置 reverse=True 选择降序排序。

doc_sorted_tfidfs =[]  # 带有tfidf权重的文档特征列表
# 对文档的每个字典进行排序
for dn in tfidf_vectors:
    newD = sorted(dn.items(), key=lambda x: x[1], reverse=True)
    newD = dict(newD)
    doc_sorted_tfidfs.append(newD)

现在可以获得没有权重的关键字列表

tfidf_kw = []
for doc_tfidf in doc_sorted_tfidfs:
    ll = list(doc_tfidf.keys())
    tfidf_kw.append(ll)

为第一个文档选择前 5 个关键字。

TopN= 5
print(tfidf_kw[0][0:TopN])
['cone', 'cone tree', 
'dimensional', 'shadow',
'visualization']

性能评估

以上方法足以使用其提取关键词或关键短语,但在下文中,希望根据此类任务的标准度量,以科学的方式评估该方法的有效性。

首先使用精确匹配进行评估,从文档中自动提取的关键短语必须与文档的黄金标准关键字完全匹配。

def get_exact_intersect(doc_orginal_kw, doc_my_kw):
    general = []
    for kw in doc_my_kw:
        for kww in doc_orginal_kw:
            l_my = len(kw.split())
            l_org = len(kww.split())
            if (kw == kww):
#                 print("exact matching ========", kw, kww)
                if kww not in general:
                    general.append(kww) 
    return general

get_exact_intersect(orginal_kw[0], tfidf_kw[0])
['visualization',
 'animation',
 'unix',
 'dimension',
 'cod',
 'icon',
 'shape',
 'fisheye lens',
 'rapid prototyping',
 'script language',
 'tree structure',
 'programming language']

关键字提取是一个排名问题。最常用的排名度量之一是"Mean average precision at K(K处的平均精度), MAP@K"。为了计算MAP@K ,首先将 " precision at K elements(k处的精度), p@k "视为一个文档的排名质量的基本指标。

def apk(kw_actual, kw_predicted, k=10):
    if len(kw_predicted)>k:
        kw_predicted = kw_predicted[:k]
    score = 0.0
    num_hits = 0.0
    for i,p in enumerate(kw_predicted):
        if p in kw_actual and p not in kw_predicted[:i]:
            num_hits  = 1.0
            score  = num_hits / (i 1.0)
    if not kw_actual:
        return 0.0
    return score / min(len(kw_actual), k)

def mapk(kw_actual, kw_predicted, k=10):
    return np.mean([apk(a,p,k) for a,p in zip(kw_actual, kw_predicted)])

此函数apk接受两个参数:TFIDF 方法预测的关键字列表(kw_predicted)和黄金标准关键字列表(kw_actual)。k 的默认值为 10。这里在 k=[5,10,20,40] 处打印 MAP 值。

for k in [5, 10,20,40]:
    mpak= mapk(orginal_kw, tfidf_kw, k)
    print("mean average precession  @",k,
          '=  {0:.4g}'.format(mpak))
mean average precession  @ 5 =  0.2037
mean average precession  @ 10 =  0.1379
mean average precession  @ 20 =  0.08026
mean average precession  @ 40 =  0.05371

在本文中,我们介绍了一种使用TFIDF和Python从文档中提取关键字的简单方法。用Python编写代码并逐步解释。将MAP标准作为一个排序任务来评价该方法的性能。这种方法虽然简单,但非常有效,被认为是该领域的有力基线之一。

附录

文本预处理preprocess_text函数。

def preprocess_text(text):
    # 1. 将其标记为字母符号
    text = remove_numbers(text)
    text = remove_http(text)
    text = remove_punctuation(text)
    text = convert_to_lower(text)
    text = remove_white_space(text)
    text = remove_short_words(text)
    tokens = toknizing(text)
    # 2. POS tagging
    pos_map = {'J': 'a', 'N': 'n', 'R': 'r', 'V': 'v'}
    pos_tags_list = pos_tag(tokens)
    # print(pos_tags)
    # 3. 小写变换和词形还原 
    lemmatiser = WordNetLemmatizer()
    tokens = [lemmatiser.lemmatize(w.lower(), 
                                   pos=pos_map.get(p[0], 'v')) 
              for w, p in pos_tags_list]
    return tokens

def convert_to_lower(text):
    # 小写转换
    return text.lower()

def remove_numbers(text):
    # 除去数字
    text = re.sub(r'\d ' , '', text)
    return text

def remove_http(text):
    # 除去网址
    text = re.sub("https?:\/\/t.co\/[A-Za-z0-9]*", ' ', text)
    return text

def remove_short_words(text):
    # 去除短于三个字母的单词
    text = re.sub(r'\b\w{1,2}\b', '', text)
    return text

def remove_punctuation(text):
    # 去除符号和标点符号
    punctuations = '''!()[]{};«№»:'"\,`<>./?@=#$-(%^) &[*_]~'''
    no_punct = ""
     
    for char in text:
        if char not in punctuations:
            no_punct = no_punct   char
    return no_punct

def remove_white_space(text):
    # 去除空格
    text = text.strip()
    return text

def toknizing(text):
    stp = my_stopwords
    #stops = set(stopwords.words('english'))
    stop_words = set(stp)
    tokens = word_tokenize(text)
    ## 从tokens中去除停用词
    result = [i for i in tokens if not i in stop_words]
    return result

以上就是基于Python和TFIDF实现提取文本中的关键词的详细内容,更多关于Python TFIDF提取文本关键词的资料请关注Devmax其它相关文章!

基于Python和TFIDF实现提取文本中的关键词的更多相关文章

  1. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  2. Swift基本使用-函数和闭包(三)

    声明函数和其他脚本语言有相似的地方,比较明显的地方是声明函数的关键字swift也出现了Python中的组元,可以通过一个组元返回多个值。传递可变参数,函数以数组的形式获取参数swift中函数可以嵌套,被嵌套的函数可以访问外部函数的变量。可以通过函数的潜逃来重构过长或者太复杂的函数。

  3. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  4. Swift、Go、Julia与R能否挑战 Python 的王者地位

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 红薯因 Swift 重写开源中国失败,貌似欲改用 Python

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  6. 你没看错:Swift可以直接调用Python函数库

    上周Perfect又推出了新一轮服务器端Swift增强函数库:Perfect-Python。对,你没看错,在服务器端Swift其实可以轻松从其他语种的函数库中直接拿来调用,不需要修改任何内容。以如下python脚本为例:Perfect-Python可以用下列方法封装并调用以上函数,您所需要注意的仅仅是其函数名称以及参数。

  7. Swift中的列表解析

    在Swift中完成这个的最简单的方法是什么?我在寻找类似的东西:从Swift2.x开始,有一些与你的Python样式列表解析相当的东西。(在这个意义上,它更像是Python的xrange。如果你想保持集合懒惰一路通过,只是这样说:与Python中的列表解析语法不同,Swift中的这些操作遵循与其他操作相同的语法。

  8. swift抛出终端的python错误

    每当我尝试启动与python相关的swift时,我都会收到错误.我该如何解决?

  9. 在Android上用Java嵌入Python

    解决方法看看this,它适用于J2SE,你可以尝试在Android上运行.

  10. 在android studio中使用python代码构建android应用程序

    我有一些python代码和它的机器人,我正在寻找一种方法来使用android项目中的那些python代码.有没有办法做到这一点!?解决方法有两种主要工具可供使用,它们彼此不同:>QPython>Kivy使用Kivy,大致相同的代码也可以部署到IOS.

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部