百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

使用NLP从文章中自动提取关键字详细指南

toyiye 2024-06-21 12:21 18 浏览 0 评论

背景

在研究和新闻文章中,关键词构成了一个重要的组成部分,因为它们提供了文章内容的简洁表示。关键词在从信息检索系统,书目数据库和搜索引擎优化中定位文章方面也起着至关重要的作用。关键词还有助于将文章分类为相关主题或学科。

提取关键词的传统方法涉及基于文章内容和作者的判断手动分配关键词。这涉及大量时间和精力,并且在选择适当的关键字方面也可能不准确。随着自然语言处理(NLP)的出现,关键字提取已经发展为有效且高效。

在本文中,我们将结合这两者 - 我们将在一系列文章上应用NLP来提取关键字。

关于数据集

在本文中,我们将从包含大约3,800个摘要的机器学习数据集中提取关键字。机器学习原始数据集来自Kaggle - NIPS Paper(https://www.kaggle.com/benhamner/nips-papers/home)。神经信息处理系统(NIPS)是世界顶级机器学习会议之一。该数据集包括迄今为止所有NIPS论文的标题和摘要(从1987年的第一次会议到当前的2016年会议)。

原始数据集还包含文章文本。然而,由于重点是理解关键字提取的概念,使用全文可能需要大量的计算,所以只有摘要被用于NLP建模。可以在全文中使用相同的代码块来获得更好的增强关键字提取。

高级方法

导入数据集

本文使用的数据集是Kaggle上NIPS Paper数据集中提供的papers.csv数据集的子集。仅使用了包含摘要的那些行。标题和摘要已连接在一起,之后文件将另存为制表符分割的* .txt文件。

import pandas
# load the dataset
dataset = pandas.read_csv('papers2.txt', delimiter = '\t')
dataset.head()

我们可以看到,机器学习数据集包含文章ID,发布年份和摘要。

初步文本探索

在我们继续进行任何文本预处理之前,建议您根据字数,最常见和最不常见的单词快速浏览数据集。

获取每个摘要的字数

#Fetch wordcount for each abstract
dataset['word_count'] = dataset['abstract1'].apply(lambda x: len(str(x).split(" ")))
dataset[['abstract1','word_count']].head()

##Descriptive statistics of word counts
dataset.word_count.describe()

每个摘要的平均字数约为156个字。单词计数范围从最小值27到最大值325.单词计数对于向我们指示我们正在处理的数据集的大小以及跨行的单词计数的变化非常重要。

最常见和最不常见的词

浏览一下最常用的单词,不仅可以洞察经常使用的单词,还可以洞察可能是特定于数据的潜在停止词的单词。比较最常用的单词和默认的英语停止词,我们将得到需要添加到自定义停止词列表中的单词列表。

#Identify common words
freq = pandas.Series(' '.join(dataset['abstract1']).split()).value_counts()[:20]
freq

最常见的词

#Identify uncommon words
freq1 = pandas.Series(' '.join(dataset 
 ['abstract1']).split()).value_counts()[-20:]
freq1

文字预处理

文本预处理的目标

稀疏性:在文本挖掘中,基于词频创建巨大的矩阵,其中许多单元具有零值。这个问题被称为稀疏性,并使用各种技术最小化。

文本预处理可分为两大类 - 噪声消除和归一化。对核心文本分析而言冗余的数据组件可视为噪声。

文本预处理

处理同一个单词的多个出现/表示称为标准化。归一化有两种类型 - 词干提取和词形还原。让我们考虑一下learn这个词的各种版本的例子 - learn, learned, learning, learner。归一化会将所有这些单词转换为单个标准化版本 - “learn”。

词干通过删除后缀来归一化文本。

Lemmatisation是一种更先进的技术,它基于基于词根。

以下示例说明了词干和lemmatisation的工作方式:

from nltk.stem.porter import PorterStemmer
from nltk.stem.wordnet import WordNetLemmatizer
lem = WordNetLemmatizer()
stem = PorterStemmer()
word = "inversely"
print("stemming:",stem.stem(word))
print("lemmatization:", lem.lemmatize(word, "v"))

要对我们的数据集执行文本预处理,我们将首先导入所需的Python库。

# Libraries for text preprocessing
import re
import nltk
#nltk.download('stopwords')
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
from nltk.tokenize import RegexpTokenizer
#nltk.download('wordnet') 
from nltk.stem.wordnet import WordNetLemmatizer

删除停止词(stopwords):停止词包括句子中的大量介词,代词,连词等。在分析文本之前,需要删除这些单词,以便经常使用的单词主要是与上下文相关的单词,而不是文本中使用的常用单词。

python nltk库中有一个默认的停止词列表。此外,我们可能希望添加特定于上下文的停止词,我们在开头列出的“最常用词”对此有用。我们现在将看到如何创建一个停止词列表以及如何添加自定义停止词:

##Creating a list of stop words and adding custom stopwords
stop_words = set(stopwords.words("english"))
##Creating a list of custom stopwords
new_words = ["using", "show", "result", "large", "also", "iv", "one", "two", "new", "previously", "shown"]
stop_words = stop_words.union(new_words)

我们现在将逐步执行预处理任务,以获得清理和归一化的文本语料库:

corpus = []
for i in range(0, 3847):
 #Remove punctuations
 text = re.sub('[^a-zA-Z]', ' ', dataset['abstract1'][i])
 
 #Convert to lowercase
 text = text.lower()
 
 #remove tags
 text=re.sub("</?.*?>"," <> ",text)
 
 # remove special characters and digits
 text=re.sub("(\\d|\\W)+"," ",text)
 
 ##Convert to list from string
 text = text.split()
 
 ##Stemming
 ps=PorterStemmer()
 #Lemmatisation
 lem = WordNetLemmatizer()
 text = [lem.lemmatize(word) for word in text if not word in 
 stop_words] 
 text = " ".join(text)
 corpus.append(text)

现在让我们从语料库中查看一个项:

#View corpus item
corpus[222]

数据探索

现在,我们将可视化我们在预处理后创建的文本语料库,以获得对最常用单词的分析。

#Word cloud
from os import path
from PIL import Image
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
import matplotlib.pyplot as plt
% matplotlib inline
wordcloud = WordCloud(
 background_color='white',
 stopwords=stop_words,
 max_words=100,
 max_font_size=50, 
 random_state=42
 ).generate(str(corpus))
print(wordcloud)
fig = plt.figure(1)
plt.imshow(wordcloud)
plt.axis('off')
plt.show()
fig.savefig("word1.png", dpi=900)

词云

文本准备

语料库中的文本需要转换为可由机器学习算法解释的格式。这种转换有两部分 - 标记化和矢量化。

标记化是将连续文本转换为单词列表的过程。然后通过矢量化过程将单词列表转换为整数矩阵。矢量化也称为特征提取。

对于文本准备,我们使用bag of words模型,它忽略了单词的顺序,只考虑单词频率。

创建单词计数向量

作为转换的第一步,我们将使用CountVectoriser来标记文本并构建已知单词的词汇表。我们首先创建CountVectoriser类的变量“cv”,然后调用fit_transform函数来学习和构建词汇表。

from sklearn.feature_extraction.text import CountVectorizer
import re
cv=CountVectorizer(max_df=0.8,stop_words=stop_words, max_features=10000, ngram_range=(1,3))
X=cv.fit_transform(corpus)

现在让我们了解传递给函数的参数:

  • cv = CountVectorizer(max_df = 0.8,stop_words = stop_words,max_features = 10000,ngram_range =(1,3))
  • max_df - 构建词汇表时,忽略文档频率严格高于给定阈值的项(语料库特定的停止词)。这是为了确保我们只有与上下文相关的单词而不是常用单词。
  • max_features - 确定矩阵中的列数。
  • n-gram范围 - 我们希望查看单个单词,两个单词(bi-gram)和三个单词(tri-gram)组合的列表。

返回具有整个词汇长度的编码向量。

list(cv.vocabulary_.keys())[:10]

可视化前N个uni-grams, bi-grams & tri-grams

我们可以使用CountVectoriser来显示前20个unigrams,bi-gram和tri-gram。

#Most frequently occuring words
def get_top_n_words(corpus, n=None):
 vec = CountVectorizer().fit(corpus)
 bag_of_words = vec.transform(corpus)
 sum_words = bag_of_words.sum(axis=0) 
 words_freq = [(word, sum_words[0, idx]) for word, idx in 
 vec.vocabulary_.items()]
 words_freq =sorted(words_freq, key = lambda x: x[1], 
 reverse=True)
 return words_freq[:n]
#Convert most freq words to dataframe for plotting bar plot
top_words = get_top_n_words(corpus, n=20)
top_df = pandas.DataFrame(top_words)
top_df.columns=["Word", "Freq"]
#Barplot of most freq words
import seaborn as sns
sns.set(rc={'figure.figsize':(13,8)})
g = sns.barplot(x="Word", y="Freq", data=top_df)
g.set_xticklabels(g.get_xticklabels(), rotation=30)

最频繁出现的uni-grams的条形图

#Most frequently occuring Bi-grams
def get_top_n2_words(corpus, n=None):
 vec1 = CountVectorizer(ngram_range=(2,2), 
 max_features=2000).fit(corpus)
 bag_of_words = vec1.transform(corpus)
 sum_words = bag_of_words.sum(axis=0) 
 words_freq = [(word, sum_words[0, idx]) for word, idx in 
 vec1.vocabulary_.items()]
 words_freq =sorted(words_freq, key = lambda x: x[1], 
 reverse=True)
 return words_freq[:n]
top2_words = get_top_n2_words(corpus, n=20)
top2_df = pandas.DataFrame(top2_words)
top2_df.columns=["Bi-gram", "Freq"]
print(top2_df)
#Barplot of most freq Bi-grams
import seaborn as sns
sns.set(rc={'figure.figsize':(13,8)})
h=sns.barplot(x="Bi-gram", y="Freq", data=top2_df)
h.set_xticklabels(h.get_xticklabels(), rotation=45)

最频繁出现的bi-grams的条形图

#Most frequently occuring Tri-grams
def get_top_n3_words(corpus, n=None):
 vec1 = CountVectorizer(ngram_range=(3,3), 
 max_features=2000).fit(corpus)
 bag_of_words = vec1.transform(corpus)
 sum_words = bag_of_words.sum(axis=0) 
 words_freq = [(word, sum_words[0, idx]) for word, idx in 
 vec1.vocabulary_.items()]
 words_freq =sorted(words_freq, key = lambda x: x[1], 
 reverse=True)
 return words_freq[:n]
top3_words = get_top_n3_words(corpus, n=20)
top3_df = pandas.DataFrame(top3_words)
top3_df.columns=["Tri-gram", "Freq"]
print(top3_df)
#Barplot of most freq Tri-grams
import seaborn as sns
sns.set(rc={'figure.figsize':(13,8)})
j=sns.barplot(x="Tri-gram", y="Freq", data=top3_df)
j.set_xticklabels(j.get_xticklabels(), rotation=45)

最频繁发生的tri-grams的条形图

转换为整数矩阵

细化单词计数的下一步是使用TF-IDF向量化器。从countVectoriser获得的单词计数的不足之处在于,大量的某些常用单词可能会稀释语料库中更多上下文特定单词的影响。这被TF-IDF矢量化器克服,该矢量化器惩罚在整个文档中出现若干次的单词。TF-IDF是词频分数,它突出显示对上下文更重要的单词,而不是那些在文档中频繁出现的单词。

TF-IDF由2个组成部分组成:

  • TF - TF意思是词频(Term Frequency)
  • IDF - IDF意思是逆文本频率指数(Inverse Document Frequency)

from sklearn.feature_extraction.text import TfidfTransformer
 
tfidf_transformer=TfidfTransformer(smooth_idf=True,use_idf=True)
tfidf_transformer.fit(X)
# get feature names
feature_names=cv.get_feature_names()
 
# fetch document for which keywords needs to be extracted
doc=corpus[532]
 
#generate tf-idf for the given document
tf_idf_vector=tfidf_transformer.transform(cv.transform([doc]))

根据TF-IDF分数,我们可以提取分数最高的单词来获取文档的关键字

#Function for sorting tf_idf in descending order
from scipy.sparse import coo_matrix
def sort_coo(coo_matrix):
 tuples = zip(coo_matrix.col, coo_matrix.data)
 return sorted(tuples, key=lambda x: (x[1], x[0]), reverse=True)
 
def extract_topn_from_vector(feature_names, sorted_items, topn=10):
 """get the feature names and tf-idf score of top n items"""
 
 #use only topn items from vector
 sorted_items = sorted_items[:topn]
 
 score_vals = []
 feature_vals = []
 
 # word index and corresponding tf-idf score
 for idx, score in sorted_items:
 
 #keep track of feature name and its corresponding score
 score_vals.append(round(score, 3))
 feature_vals.append(feature_names[idx])
 
 #create a tuples of feature,score
 #results = zip(feature_vals,score_vals)
 results= {}
 for idx in range(len(feature_vals)):
 results[feature_vals[idx]]=score_vals[idx]
 
 return results
#sort the tf-idf vectors by descending order of scores
sorted_items=sort_coo(tf_idf_vector.tocoo())
#extract only the top n; n here is 10
keywords=extract_topn_from_vector(feature_names,sorted_items,5)
 
# now print the results
print("\nAbstract:")
print(doc)
print("\nKeywords:")
for k in keywords:
 print(k,keywords[k])

最后

理想情况下,对于IDF计算有效,它应该基于大型语料库和需要提取关键字的文本的良好代表。在我们的示例中,如果我们使用完整的文章文本而不是摘要,IDF提取将更加有效。但是,考虑到数据集的大小,我将语料库限制为仅用于演示目的的摘要。

这是一种相当简单的方法来理解NLP的基本概念,并在现实生活中使用一些python代码提供良好的实践练习。可以使用相同的方法从新闻源和社交媒体源中提取关键字。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码