可以用来分析文本数据的Python工具的完整指南

本文介绍了用于理解和可视化文本数据的Python工具,包括文本统计、Ngram、情感分析、命名实体识别等。通过实例展示了如何使用这些工具进行探索性数据分析,如在新闻标题数据集中分析词频、词云、情感和主题建模。使用了如nltk、Textblob、spaCy等库,以及pyLDAvis进行主题建模的可视化。
摘要由CSDN通过智能技术生成

探索性数据分析是任何机器学习工作流程中最重要的部分之一,自然语言处理也是如此。

但是,应该选择哪些工具来有效地浏览和可视化文本数据?

在本文(Shahul Es最初在 Neptune博客 上发布 )中,我们将讨论和实现几乎所有可以用来理解文本数据的主要技术 ,并为您提供了完成该工作的Python工具的完整指南完成。

开始之前:数据集和依赖项

在本文中,我们将使用来自Kaggle的一百万个新闻头条数据集
如果要逐步进行分析,则可能需要安装以下库:

pip install \
   pandas matplotlib numpy \
   nltk seaborn sklearn gensim pyldavis \
   wordcloud textblob spacy textstat

现在,我们来看看数据。

news= pd.read_csv( 'data/abcnews-date-text.csv' ,nrows= 10000 )
news.head( 3 )

数据集仅包含两列,即发布日期和新闻标题。

为简单起见,我将探索该数据集中的前10000行 。 由于标题是按publish_date排序的,因此实际上是 2003 2月 19日 2003 4月7 两个月

好的,我想我们已经准备好开始数据探索!

分析文本统计

文本统计可视化是简单但很有见地的技术。

它们包括:

词频分析,句长分析,平均词长分析等

这些确实有助于探索文本数据的基本特征

为此,我们将主要使用直方图 (连续数据)和条形图 (分类数据)。

首先,我来看看每个句子中存在的字符数。 这可以使我们大致了解新闻标题的长度。

news[ 'headline_text' ].str.len().hist()

生成此图表的代码段

直方图显示新闻标题的范围是10到70个字符,通常在25到55个字符之间。

现在,我们将继续逐字进行数据探索。 让我们绘制出每个新闻标题中出现的单词数。

text.str.split().\
    map( lambda x: len(x)).\
    hist()

生成此图表的代码段

显然,新闻头条中的单词数量在2到12个范围内,大部分在5到7个单词之间。

接下来,让我们检查每个句子中的平均单词长度

news[ 'headline_text' ].str.split().\
   apply( lambda x : [len(i) for i in x]). \
   map( lambda x: np.mean(x)).hist()

生成此图表的代码段

平均单词长度在3到9之间,最常见的长度是5。 这是否意味着人们在新闻标题中使用了非常简短的单词?

让我们找出答案。

可能并非如此的一个原因是停用词。 停用词是在任何语言(例如“ the”,“ a”,“ an ”等) 中最常用的词 。由于这些词的长度可能很小,因此这些词可能导致上述图形向左偏斜。

分析停用词的数量和类型可以使我们对数据有一些深入的了解。

要获取包含停用词的语料库,可以使用nltk库 。 Nltk包含来自多种语言的停用词。 由于我们只处理英文新闻,因此我将从语料库中过滤英文停用词。

import nltk
nltk.download( 'stopwords' )
stop=set(stopwords.words( 'english' ))

现在,我们将创建语料库。

corpus=[]
new= news[ 'headline_text' ].str.split()
new=new.values.tolist()
corpus=[word for i in new for word in i]

from collections import defaultdict
dic=defaultdict(int)
for word in corpus:
    if word in stop:
        dic[word]+= 1

并绘制热门停用词。

生成此图表的代码段

我们显然可以看到,在新闻头条中,诸如“ to”,“ in”和“ for”等停用词占据了主导地位。

因此,现在我们知道哪些停用词在我们的文本中频繁出现,让我们检查一下这些停用词以外的哪些单词经常出现。

我们将使用集合库中的计数器功能来对每个单词的出现进行计数并将其存储在元组列表中。 当我们在自然语言处理中处理单词级分析时,这是一个非常有用的功能

counter=Counter(corpus)
most=counter.most_common()

x, y= [], []
for word,count in most[: 40 ]:
    if (word not in stop):
        x.append(word)
        y.append(count)
        
sns.barplot(x=y,y=x)

生成此图表的代码段

哇! 在过去15年中,“美国”,“伊拉克”和“战争”占据了头条新闻。

这里的“我们”可能意味着美国或我们(您和我)。 我们不是一个停用词,但是当我们观察图中的其他单词时,它们都与美国有关-伊拉克战争和此处的“我们”可能表示美国。

Ngram探索

Ngram是n个单词的连续序列 。 例如“河岸”,“三个火枪手”等。
如果单词数为两个,则称为双字。 对于3个字,它称为三字组,依此类推。

查看最常见的n-gram可以使您对使用该词的上下文有更好的理解

要实现的n-gram,我们将使用n元语法功能从nltk.util。 例如:

from nltk.util import ngrams
list(ngrams([ 'I' , 'went' , 'to' , 'the' , 'river' , 'bank' ], 2 ))

既然我们知道如何创建n-gram,就可以对其进行可视化。

为了建立我们的词汇表,我们将使用 Countvectorizer。 Countvectorizer是一种简单的方法,用于以适当的形式标记,向量化和表示语料库。 可在sklearn.feature_engineering.text找到

因此,我们将在所有新闻头条中分析头号新闻。

def get_top_ngram (corpus, n=None) :
    vec = CountVectorizer(ngram_range=(n, n)).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[: 10 ]

top_n_bigrams=get_top_ngram(news[ 'headline_text' ], 2 )[: 10 ]
x,y=map(list,zip(*top_n_bigrams))
sns.barplot(x=y,y=x)

生成此图表的代码段

我们可以观察到,与战争有关的“反战”,“被击杀”等二元论占据了新闻头条。

三元组怎么样?

top_tri_grams=get_top_ngram(news[ 'headline_text' ],n= 3 )
x,y=map(list,zip(*top_tri_grams))
sns.barplot(x=y,y=x)

生成此图表的代码段

我们可以看到,许多这些卦都是“面对法庭”“反战抗议”的某种组合 这意味着我们应该花一些精力进行数据清理 ,看看是否能够将这些同义词组合成一个干净的令牌。

使用pyLDAvis进行主题建模探索

主题建模是使用无监督学习技术提取文档集中出现的主要主题的过程

潜在狄利克雷分配 (LDA)是一种易于使用且高效的主题建模模型。 每个文档由主题分布表示,每个主题由单词分布表示。

一旦将文档分类为主题,就可以深入研究每个主题或主题组的数据

但是在进入主题建模之前,我们必须对数据进行一些预处理。 我们会:

标记化 :将句子转换为标记或单词列表的过程。 remove stopwordslemmatize :将每个单词的变形形式简化为一个共同的基数或词根。 转换为单词袋:单词袋是一个字典,其中的键是单词(或ngram / tokens),值是每个单词在语料库中出现的次数。

借助NLTK,您可以轻松地标记化和定形化:

import nltk
nltk.download( 'punkt' )
nltk.download( 'wordnet' )

def preprocess_news (df) :
    corpus=[]
    stem=PorterStemmer()
    lem=WordNetLemmatizer()
    for news in df[ 'headline_text' ]:
        words=[w for w in word_tokenize(news) if (w not in stop)]
        
        words=[lem.lemmatize(w) for w in words if len(w)> 2 ]
        
        corpus.append(words)
    return corpus

corpus=preprocess_news(news)

现在,让我们使用gensim创建单词袋模型

dic=gensim.corpora.Dictionary(corpus)
bow_corpus = [dic.doc2bow(doc) for doc in corpus]

我们最终可以创建LDA模型:

lda_model = gensim.models.LdaMulticore(bow_corpus, 
                                   num_topics = 4 , 
                                   id2word = dic,                                    
                                   passes = 10 ,
                                   workers = 2 )
lda_model.show_topics()

主题0表示与伊拉克战争和警察有关的事物。 主题3显示了澳大利亚卷入了伊拉克战争。

您可以打印所有主题并尝试理解它们,但是有些工具可以帮助您更有效地运行此数据探索。 pyLDAvis就是这样一种工具,它可以交互式地可视化LDA的结果。

pyLDAvis.enable_notebook()
vis = pyLDAvis.gensim.prepare(lda_model, bow_corpus, dic)
vis

生成此图表的代码段

在左侧, 每个圆圈区域代表主题相对于语料库的重要性 。 因为有四个主题,所以我们有四个圈子。

圆心之间的距离表示主题之间的相似性 。 在这里您可以看到主题3和主题4重叠,这表明主题更相似。在右侧, 每个主题直方图显示了前30个相关词 。 例如,在主题1中,最相关的词是“警察”,“新”,“可能”,“战争”等

因此,在我们的案例中,我们可以在新闻头条中看到许多与战争有关的词语和话题。

词云

Wordcloud是表示文本数据的好方法。 出现在单词云中的每个单词的大小和颜色表明其出现的频率或重要性。

使用python创建wordcloud很容易,但是我们需要以语料库的形式提供数据。 幸运的是,我在上一节中做了准备。

from wordcloud import WordCloud, STOPWORDS
stopwords = set(STOPWORDS)

def show_wordcloud (data) :
    wordcloud = WordCloud(
        background_color= 'white' ,
        stopwords=stopwords,
        max_words= 100 ,
        max_font_size= 30 ,
        scale= 3 ,
        random_state= 1 )
   
    wordcloud=wordcloud.generate(str(data))

    fig = plt.figure( 1 , figsize=( 12 , 12 ))
    plt.axis( 'off' )

    plt.imshow(wordcloud)
    plt.show()

show_wordcloud(corpus)

生成此图表的代码段

同样,您可以看到与战争有关的术语被突出显示,表明这些词在新闻头条中经常出现。

许多参数可以调整 。 一些最著名的是:

stopwords :阻止出现在图像中的一组单词。 max_words :指示要显示的最大单词数。 max_font_size :最大字体大小。

还有许多其他选项可以创建漂亮的词云。 有关更多详细信息,您可以在这里参考。

情绪分析

情感分析是一种非常常见的自然语言处理任务,其中我们确定文本是肯定的,否定的还是中性的。 这对于查找与评论,评论相关的情绪非常有用,可以使我们从文本数据中获得一些有价值的见解。

有许多项目可以帮助您使用python进行情感分析。 我个人喜欢TextBlobVader Sentiment。

Textblob

Textblob是建立在nltk之上的python库。 它已经存在了一段时间,并且非常易于使用。

TextBlob的情感函数返回两个属性:

极性:是在[-1,1]范围内的浮点数,其中1表示肯定陈述, -1表示否定陈述。 主观性:是指个人的意见和感受如何影响某人的判断力 。 主观性表示为浮点值,其范围为[0,1]。

我将在新闻头条上运行此功能。

from textblob import TextBlob
TextBlob( '100 people killed in Iraq' ).sentiment

TextBlob声称“在伊拉克遇难的100人”这一文字是负面的,不是一种观点或感觉,而是事实陈述。 我认为我们可以在这里同意TextBlob。

现在,我们知道了如何计算这些情感得分, 我们可以使用直方图将其可视化,并进一步探索数据。

def polarity (text) :
    return TextBlob(text).sentiment.polarity

news[ 'polarity_score' ]=news[ 'headline_text' ].\
   apply( lambda x : polarity(x))
news[ 'polarity_score' ].hist()

生成此图表的代码段

您会看到极性主要在0.00到0.20之间。 这表明大多数新闻标题是中立的。

让我们根据得分将新闻分类为负面,正面和中性,从而进行更深入的研究。

def sentiment (x) :
    if x< 0 :
        return 'neg'
    elif x== 0 :
        return 'neu'
    else :
        return 'pos'
    
news[ 'polarity' ]=news[ 'polarity_score' ].\
   map( lambda x: sentiment(x))

plt.bar(news.polarity.value_counts().index,
        news.polarity.value_counts())

生成此图表的代码段

是的,有70%的新闻是中立的,只有18%的正面新闻和11%的负面新闻。

让我们看一下正面和负面的头条新闻。

news[news[ 'polarity' ]== 'pos' ][ 'headline_text' ].head()

正面新闻头条主要是关于体育方面的胜利。

news[news[ 'polarity' ]== 'neg' ][ 'headline_text' ].head()

是的,确实是负面新闻头条。

维达情绪分析

我们要讨论的下一个库是VADER。 维德在发现负面情绪方面表现更好 。 在社交媒体文本情感分析的情况下,它非常有用。

VADER或Valence Aware词典和情感推理器是基于规则/词典的开源情感分析器预建库,受MIT许可证保护。

VADER情绪分析类返回一个字典,其中包含文本出现肯定,否定和中立的可能性。 然后,我们可以过滤并选择可能性最高的情感。

我们将使用VADER进行相同的分析,并检查差异是否很大。

from nltk.sentiment.vader import SentimentIntensityAnalyzer

nltk.download( 'vader_lexicon' )
sid = SentimentIntensityAnalyzer()

def get_vader_score (sent) :
    # Polarity score returns dictionary
    ss = sid.polarity_scores(sent)
    #return ss
    return np.argmax(list(ss.values())[: -1 ])

news[ 'polarity' ]=news[ 'headline_text' ].\
    map( lambda x: get_vader_score(x))
polarity=news[ 'polarity' ].replace({ 0 : 'neg' , 1 : 'neu' , 2 : 'pos' })

plt.bar(polarity.value_counts().index,
        polarity.value_counts())

生成此图表的代码段

是的,分布上略有不同。 甚至有更多的头条新闻被归类为中立的85%,负面新闻头条的数量也增加了(至13%)。

命名实体识别

命名实体识别是一种信息提取方法,其中将文本中存在的实体分类为预定义的实体类型,例如“人”,“地点”,“组织”等。通过使用NER,我们可以深入了解实体类型给定文本数据集中存在的实体

让我们考虑一个新闻文章的例子。

在上述新闻中,命名实体识别模型应该能够识别
实体,例如RBI作为组织,孟买和印度作为Places等。

有三个标准库可以进行命名实体识别:

在本教程中, 我将使用spaCy ,这是一个用于高级自然语言处理任务的开源库。 它是用Cython编写的,并以其工业应用而闻名。 除了NER之外, spaCy还提供许多其他功能,例如pos标记,单词到矢量的转换等。

SpaCy的命名实体识别已在OntoNotes 5语料库上进行了训练,并且支持以下实体类型:

SpaCy中有三种针对英语的预训练模型 。 我将使用en_core_web_sm来完成我们的任务,但是您可以尝试其他模型。

要使用它,我们必须先下载它:

python -m spacy download en_core_web_sm

现在我们可以初始化语言模型:

import spacy

nlp = spacy.load( "en_core_web_sm" )

Spacy的优点之一是我们只需要应用nlp函数一次,整个后台管道将返回我们需要的对象。

doc=nlp( 'India and Iran have agreed to boost the economic viability \
of the strategic Chabahar port through various measures, \
including larger subsidies to merchant shipping firms using the facility, \
people familiar with the development said on Thursday.' )

[(x.text,x.label_) for x in doc.ents]

我们可以看到印度和伊朗被确认为地理位置(GPE),查巴哈尔(Chabahar)被确认为人,周四被确认为日期。

我们还可以使用spaCy中的显示模块可视化输出。

from spacy import displacy

displacy.render(doc, style= 'ent' )

这可以使带有识别的实体的句子看起来非常整洁,每个实体类型都用不同的颜色标记。

现在我们知道如何执行NER,我们可以通过对从数据集中提取的命名实体进行各种可视化来进一步探索数据。

首先,我们将在新闻头条上运行命名的实体识别并存储实体类型。

def ner (text) :
    doc=nlp(text)
    return [X.label_ for X in doc.ents]

ent=news[ 'headline_text' ].\
    apply( lambda x : ner(x))
ent=[x for sub in ent for x in sub]

counter=Counter(ent)
count=counter.most_common()

现在,我们可以可视化实体频率:

x,y=map(list,zip(*count))
sns.barplot(x=y,y=x)

生成此图表的代码段

现在我们可以看到,GPE和ORG主导了新闻头条,其次是PERSON实体。

我们还可以可视化每个实体最常见的令牌。 让我们检查一下哪些地方在新闻头条中出现最多。

def ner (text,ent= "GPE" ) :
    doc=nlp(text)
    return [X.text for X in doc.ents if X.label_ == ent]

gpe=news[ 'headline_text' ].apply( lambda x: ner(x))
gpe=[i for x in gpe for i in x]
counter=Counter(gpe)

x,y=map(list,zip(*counter.most_common( 10 )))
sns.barplot(y,x)

生成此图表的代码段

我认为我们可以证实事实,即“美国”在新闻头条中意味着美国。 让我们还找到出现在新闻头条上的最常见名称。

per=news[ 'headline_text' ].apply( lambda x: ner(x, "PERSON" ))
per=[i for x in per for i in x]
counter=Counter(per)

x,y=map(list,zip(*counter.most_common( 10 )))
sns.barplot(y,x)

生成此图表的代码段

萨达姆·侯赛因和乔治·布什曾在战时担任伊拉克和美国总统。 此外,我们可以看到,该模型远非完美地将“ vic govt”“ nsw govt”分类为个人而不是政府机构。

通过python中的Speach标记部分进行探索

词性(POS)标记是一种将词性标签分配给句子中的单词的方法。 语音有八个主要部分:

  • 名词(NN)-约瑟夫,伦敦,桌子,猫,老师,钢笔,城市
  • 动词(VB)-阅读,说话,奔跑,吃饭,玩耍,生活,散步,拥有,喜欢,是
  • 形容词(JJ)-美丽,快乐,悲伤,年轻,有趣,三个
  • 副词(RB)-明天慢慢,安静,非常,永远,永远也永远不要
  • 介词(IN)-在,在,在,从,在,在,在,在,在,大约,在下
  • 连词(CC)-和,或,但是,因为,所以,但是,除非,因为,如果
  • 代词(PRP)-我,你,我们,他们,他,她,它,我,我们,他们,他,她,这个
  • 感叹词(INT)-哎呀! 哇! 大! 帮帮我! 哦! 嘿! 嗨!

这不是一项简单的任务,因为在不同的上下文中,相同的单词可能会用在不同的句子中。 但是,一旦完成,便可以创建许多有用的可视化效果,从而使您对数据集有更多的了解。

我将使用nltk进行语音标记的各个部分,但是还有其他一些库可以很好地完成工作(spacy,textblob)。

让我们看一个例子。

import nltk
sentence= "The greatest comeback stories in 2019"
tokens=word_tokenize(sentence)
nltk.pos_tag(tokens)

注意:

您还可以使用spacy.displacy模块可视化语音的句子部分及其依存关系图。

doc = nlp( 'The greatest comeback stories in 2019' )
displacy.render(doc, style= 'dep' , jupyter= True , options={ 'distance' : 90 })

我们可以在这里观察各种依赖标签。 例如, DET标签表示确定词“ the”和名词“ stories”之间的关系。

您可以在此处检查依赖项标签及其含义的列表。

好的,现在我们知道POS标记是什么,让我们使用它来探索标题数据集。

def pos (text) :
    pos=nltk.pos_tag(word_tokenize(text))
    pos=list(map(list,zip(*pos)))[ 1 ]
    return pos

tags=news[ 'headline_text' ].apply( lambda x : pos(x))
tags=[x for l in tags for x in l]
counter=Counter(tags)

x,y=list(map(list,zip(*counter.most_common( 7 ))))
sns.barplot(x=y,y=x)

生成此图表的代码段

我们可以清楚地看到,名词(NN)在新闻标题中占主导地位,其次是形容词(JJ)。 这对于新闻报道是很典型的,而对于艺术形式,较高的形容词(ADJ)频率可能会发生很多。

您可以通过调查新闻标题中最常见的单数名词来对此进行更深入的研究 让我们找出答案。

def get_adjs (text) :
    adj=[]
    pos=nltk.pos_tag(word_tokenize(text))
    for word,tag in pos:
        if tag== 'NN' :
            adj.append(word)
    return adj


words=news[ 'headline_text' ].apply( lambda x : get_adjs(x))
words=[x for l in words for x in l]
counter=Counter(words)

x,y=list(map(list,zip(*counter.most_common( 7 ))))
sns.barplot(x=y,y=x)

生成此图表的代码段

新闻头条中诸如“战争”,“伊拉克”,“人”等名词占主导地位。 您可以使用上述功能来可视化和检查语音的其他部分。

探索文本的复杂性

知道文本的可读性(难于阅读)以及哪种类型的阅读器可以完全理解它可能会很有帮助。 我们是否需要大学学位才能理解这些信息,或者一年级的学生可以清楚地知道要点是什么?

实际上,您可以在文档或文本上放置一个称为可读性索引的数字。 可读性索引是一个数字值,它指示阅读和理解文本的难易程度。

有许多适用于英语的可读性得分公式。 一些最著名的是:

Textstat是一个很酷的Python库,它提供了所有这些文本统计信息计算方法的实现。 让我们使用Textstat来实现Flesch Reading Ease索引。

现在,您可以绘制分数的直方图并可视化输出。

from textstat import flesch_reading_ease

news[ 'headline_text' ].\
   apply( lambda x : flesch_reading_ease(x)).hist()

生成此图表的代码段

几乎所有可读性得分都超过60。这意味着平均11岁的学生可以阅读和理解新闻头条。 让我们检查所有可读性得分低于5的新闻标题。

x=[i for i in range(len(reading)) if reading[i]< 5 ]
news.iloc[x][ 'headline_text' ].head()

您会看到新闻标题中使用了一些复杂的词,例如“投降”,“临时”,“陷害”等。这些词可能导致得分低于5。

最后的想法

在本文中,我们讨论并实现了针对文本数据的各种探索性数据分析方法。 一些通用的,鲜为人知的,但所有这些都可能是您的数据探索工具包的绝佳补充。

希望您会发现其中一些对您当前和将来的项目有用。

为了使数据探索变得更加容易,我创建了一个“自然语言处理模板的探索性数据分析” ,您可以将其用于工作。

获取自然语言处理模板的探索性数据分析

另外,您可能已经看到, 对于本文中的每个图表,都有一个创建它的代码段 。 只需单击图表下方的按钮。

探索愉快!

From: https://hackernoon.com/a-completeish-guide-to-python-tools-you-can-use-to-analyse-text-data-13g53wgr

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值