【问题标题】:Calculating tf-idf among documents using python 2.7使用 python 2.7 在文档中计算 tf-idf
【发布时间】:2015-02-14 08:16:41
【问题描述】:

我有一个场景,我从互联网上检索信息/原始数据并将它们放入各自的 json 或 .txt 文件中。

从那时起,我想使用 tf-idf 计算每个文档中每个术语的频率及其余弦相似度。

例如: 有 50 个不同的文档/文本文件,每个文件包含 5000 个单词/字符串 我想从第一个文档/文本中取出第一个单词并比较所有 250000 个单词,找到它的频率,然后对第二个单词执行此操作,以此类推所有 50 个文档/文本。

每个频率的预期输出将从 0 -1

我怎么能这样做。我一直在提到 skear 包,但它们中的大多数在每次比较中只包含几个字符串。

【问题讨论】:

    标签: python-2.7 nltk information-retrieval tf-idf cosine-similarity


    【解决方案1】:

    您确实应该向我们展示您的代码并更详细地说明您遇到问题的部分。

    你所描述的通常不是它是如何完成的。您通常做的是将文档向量化,然后比较向量,从而得出此模型下任意两个文档之间的相似性。既然你问的是 NLTK,我会假设你想要这种常规的传统方法。

    无论如何,对于传统的词表示,两个词之间的余弦相似度是没有意义的——两个词要么相同,要么不同。但当然还有其他方法可以处理术语相似性或文档相似性。

    https://stackoverflow.com/a/23796566/874188 复制代码,这样我们就有了基线:

    from sklearn.feature_extraction.text import TfidfVectorizer
    corpus = ["This is very strange",
              "This is very nice"]
    vectorizer = TfidfVectorizer(min_df=1)
    X = vectorizer.fit_transform(corpus)
    idf = vectorizer._tfidf.idf_
    print dict(zip(vectorizer.get_feature_names(), idf))
    

    这里没有什么取决于输入的长度。如果您有更长的文档,idf 中的特征数量会更多,如果您有更多文档,语料库中的特征数量会更多,但是这样的算法根本不需要更改以容纳更多或更长的文档.

    如果您不想了解原因,可以在此处停止阅读。

    向量基本上是每个单词形式的计数数组。每个向量的长度是词形的数量(即特征的数量)。因此,如果您有一个包含六个条目的词典,如下所示:

    0: a
    1: aardvark
    2: banana
    3: fruit
    4: flies
    5: like
    

    然后输入文档“a fruit flies like abanana”将产生一个包含六个元素的向量,如下所示:

    [2, 0, 1, 1, 1, 1]
    

    因为在词典中索引为零的单词出现了两次,索引一的单词出现了零次,索引二的单词出现了一次,等等。这是一个 TF(词频)向量。它已经是一个有用的载体;您可以使用余弦距离比较其中两个,并获得它们的相似度的度量。

    IDF 因子的目的是对此进行规范化。标准化带来三个好处;在计算上,您不需要对每个文档或每个比较进行任何归一化,因此速度更快;并且该算法还对频繁出现的单词进行归一化,因此如果大多数文档包含该单词的多次出现(因此您不必进行显式停用词过滤),则“a”的多次出现被正确地视为无关紧要,而“aardvark”的多次出现" 在归一化向量中立即明显显着。此外,归一化的输出可以很容易地解释,而对于普通的 TF 向量,您必须考虑文档长度等因素才能正确理解余弦相似度比较的结果。

    所以如果“a”的DF(文档频率)为1000,词典中其他词的DF为1,则缩放向量为

    [0.002, 0, 1, 1, 1, 1]
    

    (因为我们取的是文档频率的倒数,即TF("a")*IDF("a") = TF("a")/DF("a") = 2/1000)。

    余弦相似度基本上是在 n 维空间(此处为 n=6)中解释这些向量,并查看它们的箭头彼此相距多远。为简单起见,让我们将其缩小到三个维度,并在 X 轴上绘制“a”的(IDF 缩放)数量,在 Y 轴上绘制“aardvark”出现的数量,以及“banana”出现的数量在 Z 轴上。端点 [0.002, 0, 1] 与 [0.003, 0, 1] 仅相差一点点,而 [0, 1, 0] 最终在我们想象的立方体的另一个角落,所以余弦距离很大。 (归一化意味着 1.0 是任何元素的最大值,所以我们实际上是在谈论一个角。)

    现在,回到词典,如果您添加一个新文档并且其中包含词典中不存在的单词,它们将被添加到词典中,因此从现在开始向量将需要更长的时间。 (您已经创建但现在太短的向量可以简单地扩展;迄今为止未见过的术语的术语权重显然总是为零。)如果您将文档添加到语料库中,语料库中将再有一个向量进行比较反对。但是算法不需要改变;它总是会为每个词典条目创建一个元素的向量,您可以继续使用与以前相同的方法来比较这些向量。

    您当然可以遍历这些术语,并为每个术语合成一个仅由该单个术语组成的“文档”。将其与其他单项“文档”进行比较将产生 0.0 的相似度(或 1.0 的相似度与包含相同术语但没有其他内容的文档),所以这不是很有用,但与真实世界的文档进行比较将基本上揭示每个文档中有多少比例包含您正在检查的术语。

    原始 IDF 向量告诉您每个术语的相对频率。它通常表示每个词条出现在多少个文档中(因此即使一个词条在文档中出现多次,它也只会在该词条的 DF 上加 1),尽管某些实现也允许您使用裸词条计数。

    【讨论】:

    • 关于不需要更改算法以适应具有新术语的新文档的内容似乎是对来自 OP 的一些 cmets 的响应,这些 cmets 随后被删除,显然。
    猜你喜欢
    • 2015-04-17
    • 1970-01-01
    • 1970-01-01
    • 2017-11-14
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    • 2016-02-03
    相关资源
    最近更新 更多