当前位置: 首页 > 知识库问答 >
问题:

如何使用Python和NLTK从语料库中提取关键词(不是最常见的词)?

高修筠
2023-03-14

我试图从文本或语料库中提取关键词。这些不是最常见的词,而是最“关于”文本的词。我有一个比较示例,我生成的列表与示例列表非常不同。你能给我一个指针来生成一个很好的关键字列表,其中不包括像“you”和“tis”这样的低义词吗?

我用“罗密欧与朱丽叶”作为我的文本。我的做法(见斯科特

我收到了很多像“你”、“她”和“它”这样的词,但它们并没有出现在它们的列表中,我也没有收到像“放逐”和“教堂墓地”这样的词。我得到了“罗密欧”、“朱丽叶”、“卡普莱特”和“护士”,所以我至少接近正确的轨道,如果不是真的在轨道上的话。

以下是从文本中提取单词和百分比的函数

def keywords(corpus, threshold=0):
    """ generates a list of possible keywords and the percentage of 
           occurrences.
          corpus (list): text or collection of texts
          threshold (int): min # of occurrences of word in corpus                    
              target text has threshold 3, ref corp has 0
          return percentKW: list of tuples (word, percent)                         
    """

    # get freqDist of corpus as dict. key is word, value = # occurences
    fdist = FreqDist(corpus)
    n = len(corpus)

    # create list of tuple of w meeting threshold & sort w/most common first
    t = [(k, v) for k, v in fdist.items() if v >= threshold]
    t = sorted(t, key=lambda tup: tup[1], reverse=True)

    # calculate number of total tokens
    n = len(corpus)

    # return list of tuples (word, percent word is of total tokens)
    percentKW =[(k, '%.2f'%(100*(v/n))) for k, v in t]
    return percentKW

下面是调用代码的关键部分。targetKW是R

# iterate through text list of tuples
for w, p in targetKW:
    # for each word, store the percent in KWList
    targetPerc = float(p)
    refcorpPerc = float(refcorpKWDict.get(w, 0))
    # if % in text > % in reference corpus
    if (refcorpPerc or refcorpPerc == 0) and (targetPerc > refcorpPerc):
        diff = float('%.2f'%(targetPerc - refcorpPerc))
        # save result to KWList
        KWList.append((w, targetPerc, refcorpPerc, diff))        

以下是我迄今为止所尝试的:

  • 将所有可能的关键字规范化为小写(帮助)

我正在使用Python 3.5.2在Windows 10上使用IDLE版本3.5.2。

来源:在“Python自然语言处理”中(http://www.nltk.org/book/)练习4.24是“阅读‘关键字链接’”(第5章)

谢谢你抽出时间。

共有3个答案

申屠乐池
2023-03-14

你的代码的问题在于你对你所接受的“关键字”过于宽容:任何在你的文本中出现的频率比在参考语料库中出现的频率稍高的单词都会被视为关键字。从逻辑上讲,这将使你获得文本中没有特殊地位的单词的一半。

if (refcorpPerc or refcorpPerc == 0) and (targetPerc > refcorpPerc):
    # accept it as a "key word"

为了使测试更具选择性,请选择一个更大的阈值或使用更智能的度量,如“排名外度量”(google it),和/或对候选关键字进行排名,并仅保留列表的顶部,即相对频率增加最多的关键字。

章绪
2023-03-14

两种可能有用的技术(可能会偏离书本的轨道)是术语频率反向文档频率(通常是TFIDF)单词加权...和搭配。

TFIDF用于确定与更大的类似文档语料库相比,文档中的重要单词是什么。它通常被用作机器学习的一个初步步骤,用于自动分类(情绪分析等)

TFIDF基本上着眼于整个剧本语料库,并根据每个剧本中单词的重要性为每个单词实例分配一个值,并根据该词在整个语料库中的重要性进行加权。因此,您最好将您的TFIDF模型“适合”整个莎士比亚戏剧语料库(包括《罗密欧与朱丽叶》),然后将《罗密欧与朱丽叶》转换为一系列文字乐谱。然后你会发现得分最高的术语,这些术语对罗密欧和朱丽叶来说是最重要的,在所有莎士比亚戏剧的背景下。

我发现一些TFIDF指南很有帮助...

https://buhrmann.github.io/tfidf-analysis.html

http://www.ultravioletanalytics.com/2016/11/18/tf-idf-basics-with-pandas-scikit-learn/

搭配在NLTK中可用,并且相当容易实现。搭配寻找通常同时出现的短语和单词。这些通常也有助于指示文本是关于什么的。http://www.nltk.org/howto/collocations.html

如果任何一种技术都感兴趣,我很乐意帮助代码

秦俊友
2023-03-14

我已经在为一个项目复习TF-IDF,所以我们开始吧。基本上不需要在代码本身中使用Pandas或Numpy函数,尽管我强烈建议使用Pandas作为管理数据的工具。您将需要Scikit学习TFIDF矢量化。如果你还没有得到它,你需要先安装它。看起来只需使用pip install scikit learn[alldeps]就可以了,但就我个人而言,我使用的是Anaconda,它已经全部预装好了,所以我没有处理这方面的问题。我已经一步一步地分解了在《罗密欧与朱丽叶》中寻找重要术语的过程。下面还有更多的步骤来解释每个对象的含义,但是包含必要步骤的完整代码位于底部。

from sklearn.feature_extraction.text import TfidfVectorizer

# Two sets of documents
# plays_corpus contains all documents in your corpus *including Romeo and Juliet*
plays_corpus = ['This is Romeo and Juliet','this is another play','and another','and one more']

#romeo is a list that contains *just* the text for Romeo and Juliet
romeo = [plays_corpus[0]] # must be in a list even if only one object

# Initialise your TFIDF Vectorizer object
tfidf_vectorizer = TfidfVectorizer()

# Now create a model by fitting the vectorizer to your main plays corpus. This is essentially an array of TFIDF scores.
model =  tfidf_vectorizer.fit_transform(plays_corpus)

如果你好奇的话,这就是数组的样子。每一行代表语料库中的一个文档,而每一列是按字母顺序排列的每个唯一术语。在本例中,行跨越两行,术语为[‘和’、‘另一’、‘是’、‘朱丽叶’、‘更多’、‘一’、‘玩’、‘罗密欧’、‘这个’]。

tfidf_vectorizer.fit_transform(plays_corpus).toarray()
array([[ 0.33406745,  0.        ,  0.41263976,  0.52338122,  0.        ,
         0.        ,  0.        ,  0.52338122,  0.41263976],
       [ 0.        ,  0.46580855,  0.46580855,  0.        ,  0.        ,
         0.        ,  0.59081908,  0.        ,  0.46580855],
       [ 0.62922751,  0.77722116,  0.        ,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.41137791,  0.        ,  0.        ,  0.        ,  0.64450299,
         0.64450299,  0.        ,  0.        ,  0.        ]])

接下来,我们创建一个所有唯一的术语的列表(这就是我如何知道上述唯一术语的)。

terms = tfidf_vectorizer.get_feature_names()

现在我们有了tfidf分数的主要模型,它在每个文档中分别对每个术语进行评分,相对于其在直接上下文(文档)和更大上下文(语料库)中的重要性。

为了找出《罗密欧与朱丽叶》中特定术语的分数,我们现在。使用我们的模型转换该文档。

romeo_scored = tfidf_vectorizer.transform(romeo) # note .transform NOT .fit_transform

这又创建了一个数组,但是只有一行(因为只有一个doc)。

romeo_scored.toarray()
array([[ 0.33406745,  0.        ,  0.41263976,  0.52338122,  0.        ,
         0.        ,  0.        ,  0.52338122,  0.41263976]])

我们可以很容易地将这个数组转换成分数列表

# we first view the object as an array, 
# then flatten it as the array is currently like a list in a list.
# Then we transform that array object into a simple list object.
scores = romeo_scored.toarray().flatten().tolist()    

现在我们有了模型中的术语列表,以及每个术语的分数列表,具体针对罗密欧和朱丽叶。它们的顺序是相同的,这意味着我们可以把它们放在一个元组列表中。

data = list(zip(terms,scores)

# Which looks like
[('and', 0.3340674500232949),
 ('another', 0.0),
 ('is', 0.41263976171812644),
 ('juliet', 0.5233812152405496),
 ('more', 0.0),
 ('one', 0.0),
 ('play', 0.0),
 ('romeo', 0.5233812152405496),
 ('this', 0.41263976171812644)]

现在我们只需要按分数排序就可以得到最重要的项目

# Here we sort the data using 'sorted',
# we choose to provide a sort key,
# our key is lambda x: x[1]
# x refers to the object we're processing (data)
# and [1] specifies the second part of the tuple - the score.
# x[0] would sort by the first part - the term.
# reverse = True switches from Ascending to Descending order.

sorted_data = sorted(data, key=lambda x: x[1],reverse=True)

最终,在这一切给了我们...

[('juliet', 0.5233812152405496),
 ('romeo', 0.5233812152405496),
 ('is', 0.41263976171812644),
 ('this', 0.41263976171812644),
 ('and', 0.3340674500232949),
 ('another', 0.0),
 ('more', 0.0),
 ('one', 0.0),
 ('play', 0.0)]

通过对列表进行切片,您可以将其限制为前N个术语。

sorted_data[:3]
[('juliet', 0.5233812152405496),
 ('romeo', 0.5233812152405496),
 ('is', 0.41263976171812644)]
from sklearn.feature_extraction.text import TfidfVectorizer,CountVectorizer

# Two sets of documents
# plays_corpus contains all documents in your corpus *including Romeo and Juliet*
plays_corpus = ['This is Romeo and Juliet','this is another play','and another','and one more']

#romeo is a list that contains *just* the text for Romeo and Juliet
romeo = [plays_corpus[0]] # must be in a list even if only one object

# Initialise your TFIDF Vectorizer object
tfidf_vectorizer = TfidfVectorizer()

# Now create a model by fitting the vectorizer to your main plays corpus, this creates an array of TFIDF scores
model = tfidf_vectorizer.fit_transform(plays_corpus)

romeo_scored = tfidf_vectorizer.transform(romeo) # note - .fit() not .fit_transform

terms = tfidf_vectorizer.get_feature_names()

scores = romeo_scored.toarray().flatten().tolist()

data = list(zip(terms,scores))

sorted_data = sorted(data,key=lambda x: x[1],reverse=True)

sorted_data[:5]

 类似资料:
  • 我是新的Python和nltk。我已经将代码从https://gist.github.com/alexbowe/879414转换为下面给定的代码,使其运行于许多文档/文本块。但我得到了以下错误 有人能帮我解决这个问题吗。我必须从数以百万计的产品评论中提取名词短语。我使用了使用Java的Standford NLP工具包,但速度非常慢,所以我认为在python中使用nltk会更好。如果有更好的解决方案

  • 问题内容: 我正在尝试学习如何使用NLTK标记西班牙语单词。 从nltk的书中,使用它们的示例标记英语单词非常容易。因为我是nltk和所有语言处理的新手,所以我对如何进行程序感到很困惑。 我已经下载了语料库。有没有办法指定一个语料库。我看了看文档,没有发现任何建议。我觉得我缺少一些关键概念。我是否需要在cess_esp语料库中手动标记文本中的单词?(通过手动,我的意思是标记我的情感,然后再次运行语

  • 问题内容: 我认为标题的答案通常是去阅读文档,但是我浏览了NLTK书,但没有给出答案。我是Python的新手。 我有很多文件,我希望能够使用NLTK为语料库提供的语料库功能。 我已经尝试过,但是我无法超越: 如何使用分割句子?我尝试使用函数,但函数无法读取类? 你还可以引导我介绍如何将分段数据写入文本文件吗? 问题答案: 我认为,至少在你的输入语言是英语的情况下,已经使用punkt标记器对输入进行

  • 问题内容: 我认为标题的答案通常是去阅读文档,但是我遍历了NLTK书,但没有给出答案。我是Python的新手。 我有很多文件,我希望能够使用NLTK为语料库提供的语料库功能。 我已经尝试过,但是我无法超越: 如何使用punkt分割句子?我尝试使用punkt函数,但punkt函数无法读取类? 您还可以引导我介绍如何将分段数据写入文本文件吗? 问题答案: 我认为,至少在您的输入语言是英语的情况下,已经

  • 本文向大家介绍在Python中使用NLTK库实现对词干的提取的教程,包括了在Python中使用NLTK库实现对词干的提取的教程的使用技巧和注意事项,需要的朋友参考一下 什么是词干提取? 在语言形态学和信息检索里,词干提取是去除词缀得到词根的过程─—得到单词最一般的写法。对于一个词的形态词根,词干并不需要完全相同;相关的词映射到同一个词干一般能得到满意的结果,即使该词干不是词的有效根。从1968年开

  • 问题内容: WordNet很棒,但是我很难在nltk中获得同义词。如果您在此处类似地搜索“ small”一词,则会显示所有同义词。 基本上,我只需要了解以下内容: 哪里的选项可以是化名和反义词,但是获取同义词的选择是什么? 问题答案: 如果您想要同义词集中的同义词(又称组成集合的引理),则可以使用以下命令获取它们: