【问题标题】:What's a good measure for classifying text documents?对文本文档进行分类的好方法是什么?
【发布时间】:2018-05-10 02:11:50
【问题描述】:

我编写了一个测量文本重要性的应用程序。它需要一篇文本文章,将其拆分为单词,删除停用词,执行词干提取,并计算词频和文档频率。词频是衡量给定单词在所有文档中出现次数的度量,而文档频率是衡量给定单词出现多少文档的度量。

下面是两个文本文章的示例:

  • Article I) “一只狐狸跳过另一只狐狸。”
  • Article II) “猎人看到了狐狸。”

文章 I 被拆分成单词(在词干和停用词之后):

  • [“狐狸”、“跳跃”、“另一个”、“狐狸”].

第二条被拆分成文字:

  • [“猎人”、“看”、“狐狸”]。

这两篇文章产生以下词频和文档频率计数器:

  • fox(词频:3,文档频:2)
  • jump(词频:1,文档频:1)
  • another(词频:1,文档频:1)
  • hunter(词频:1,文档频:1)
  • see(词频:1,文档频:1)

给定一篇新的文字文章,我如何衡量这篇文章与以前的文章的相似程度?

我读过关于 df-idf measure 但它不适用于这里,因为我要删除停用词,所以像“a”和“the”这样的词不会出现在计数器中。

例如,我有一篇新的文字文章说“猎人爱狐狸”,我如何想出一个衡量标准,表明这篇文章与之前看到的文章非常相似?

另一个例子,我有一篇新的文字文章说“鹿很有趣”,那么这是一篇全新的文章,相似度应该是0。

我想我需要以某种方式将词频和文档频率计数器值相加,但有什么好的公式可以使用?

【问题讨论】:

    标签: text nlp similarity words measure


    【解决方案1】:

    一个标准的解决方案是应用朴素贝叶斯分类器,它估计给定文档 DC 的后验概率,表示为 P(C= k|D)(对于二元分类问题,k=0 和 1)。

    这是通过从一组标记为文档的训练集中计算先验来估计的,其中给定文档D,我们知道它的类C

    P(C|D) = P(D|C) * P(D)              (1)
    

    朴素贝叶斯假设项是独立的,在这种情况下,您可以将 P(D|C) 写为

    P(D|C) = \prod_{t \in D} P(t|C)     (2)
    

    P(t|C) 可以简单地通过计算一个术语在给定类中出现的次数来计算,例如您希望单词 football 会在属于类(类别)sports 的文档中大量出现。

    当涉及到另一个因素 P(D) 时,您可以通过计算每个类别给出多少标记文档来估计它,可能您有更多的运动 文章而不是金融 文章,这使您相信未见过的文档被归类到体育 类别的可能性更高。

    很容易将诸如术语重要性 (idf) 或术语相关性等因素纳入等式 (1)。对于 idf,您将其添加为集合中的术语采样事件(与类无关)。 对于术语依赖性,您必须插入 P(u|C)*P(u|t) 形式的概率,这意味着您采样不同的术语 u 和将其更改(转换)为 t

    朴素贝叶斯分类器的标准实现可以在Stanford NLP packageWekaScipy 等中找到。

    【讨论】:

    • 很好的答案!我想知道如果我只有一门课,那会发生什么变化。我需要为 P(D|C) 设置一个阈值,以确定文档是否属于这个单一的 C 类。对吗?
    • 是的,阈值化是一种方法......即使您只有一个课程(例如运动),您也可以将另一个课程视为补充课程(例如不是运动) - 然后在测试时,您检测哪些属于该类,哪些是异常值...
    • 我已经实施了这个解决方案,但存在一些严重的问题。你能帮忙解决它们吗?第一个问题是我只使用 TF 而我不使用 DF,所以我只使用部分信息。我如何在方程中包含 DF(不使用 IDF)?也许 TF*DF 的总和?第二个问题是我如何在 0 和 1 之间标准化这个分数。在我的情况下,当我将所有 TF 相乘时,它会增长到 8900 或 11854 之类的东西——对于更长的文档来说,这个数字非常大。第三个问题很长文档匹配所有单词,因此最终值是天文数字,因为它是所有 TF 的产物。短文档也有类似的问题
    • 对于第一期 - 定义 P(t|C) = lambda * tf(t,d) / doclength(d) + (1-lambda) * collection freq (t) / total number of集合中的标记...您可以用文档频率(DF)替换集合频率,这会给您类似的结果...这解决了您的第二个问题,因为这些值介于 [0,1] 之间(它们的线性组合也是如此) .
    • 关于乘法 - 而不是计算 P(D|C) - 计算 log(P(D|C)) 在这种情况下,乘法将被转换为对数求和并且不会溢出.. .
    【解决方案2】:

    您似乎正在尝试回答几个相关的问题:

    1. 如何衡量文档 A 和 B 之间的相似度? (度量学习)
    2. 与某些文档集合相比,如何衡量文档 C 的异常程度? (异常检测)
    3. 如何将一组文档分成相似的组? (聚类)
    4. 如何预测文档属于哪个类? (分类)

    所有这些问题通常分两步解决:

    1. 提取特征:文档 --> 表示(通常是数字向量)
    2. 应用模型:表示 --> 结果(通常是单个数字)

    特征工程和建模都有很多选择。这里只是一些。

    特征提取

    1. 词袋:文档 --> 每个词的出现次数(即词频)。这是基本选项,但不是唯一选项。
    2. n-gram 包(在单词级别或字符级别):考虑了多个标记的共现。
    3. 词袋 + 语法特征(例如 POS 标签)
    4. 词嵌入包(通过外部模型学习,例如 word2vec)。您可以将嵌入用作序列或取它们的加权平均值。
    5. 您可以发明的任何东西(例如基于字典查找的规则)...

    特征可能会被预处理,以减少其中的相对噪声量。一些预处理选项是:

    • 按 IDF 划分,如果您没有硬性停用词列表或认为这些词可能或多或少是“停用词”
    • 将每列(例如字数)归一化,使其均值和单位方差为零
    • 记录字数以减少噪音
    • 标准化每一行以使 L2 范数等于 1

    您无法提前知道哪个选项最适合您的特定应用 - 您必须进行实验。

    现在您可以构建 ML 模型。 4 个问题中的每一个都有自己好的解决方案。

    对于分类这个研究得最好的问题,您可以使用多种模型,包括朴素贝叶斯、k-最近邻、逻辑回归、SVM、决策树和神经网络。同样,您无法提前知道哪个性能最好。

    这些模型中的大多数都可以使用几乎任何类型的功能。但是,KNN 和基于内核的 SVM 要求您的特征具有特殊的结构:在欧几里德距离度量的意义上,一类文档的表示应该彼此接近。这有时可以通过简单的线性和/或对数归一化来实现(见上文)。更困难的情况需要非线性变换,原则上可以通过神经网络学习。学习这些变换就是人们称之为度量学习的东西,一般来说这是一个尚未解决的问题。

    最传统的距离度量确实是欧几里得。然而,其他距离度量(例如曼哈顿距离)或不同的方法也是可能的,而不是基于文本的向量表示。例如,您可以尝试根据将一个文本转换为另一个文本所需的操作数来计算文本之间的 Levenstein 距离。或者您可以计算“word mover distance” - 具有最接近嵌入的词对的距离总和。

    对于聚类,基本选项是 K-means 和 DBScan。这两种模型都要求您的特征空间具有此欧几里得属性。

    对于异常检测,您可以使用由各种概率算法产生的密度估计:分类(例如朴素贝叶斯或神经网络)、聚类(例如混合高斯模型)或其他无监督方法(例如概率 PCA)。对于文本,您可以利用顺序语言结构,以前面的单词为条件估计每个单词的概率(使用 n-gram 或卷积/递归神经网络) - 这称为 语言模型,它是通常比忽略词序的朴素贝叶斯的词袋假设更有效。多个语言模型(每个类别一个)可以组合成一个分类器。

    无论您解决什么问题,强烈建议使用已知“ground truth”的良好测试集:哪些文档彼此接近,或者属于同一类,或者是(异常。使用此套件,您可以评估特征工程和建模的不同方法,并选择最佳方法。

    如果您没有资源或不愿意进行多次实验,我建议您选择以下方法之一来评估文本之间的相似性:

    • 字数+idf归一化+L2归一化(相当于@mcoav的解)+欧几里得距离
    • 平均 word2vec 嵌入文本中的所有单词(嵌入字典可以用谷歌搜索和下载)+ 欧几里得距离

    基于这些表示之一,您可以为其他问题构建模型 - 例如。用于分类的 KNN 或用于聚类的 k-means。

    【讨论】:

      【解决方案3】:

      我建议使用 tf-idf 和 cosine similarity

      如果您放弃停用词,您仍然可以使用 tf-idf。甚至有可能是否包含停用词不会产生如此大的影响:逆文档频率测量会自动降低停用词的权重,因为它们非常频繁并且出现在大多数文档中。

      如果您的新文档完全由未知词组成,则与每个已知文档的余弦相似度将为 0。

      【讨论】:

      • 问题是,如果我在原始示例中使用 IDF,那么“狐狸”这个词就会变得毫无意义(被降低权重),但在我的示例中它是非常重要的术语,而不是停用词。这就是我想知道 IDF 的原因。
      • 朴素贝叶斯可以使用标准化的 tf-tdf 计数,而不仅仅是标准化的 tf 计数...
      • IDF 在大量文章/文档中更有意义。它惩罚出现在大多数文档中的术语:在实践中,这些术语大多是停用词。如果你的集合足够大,fox 的 IDF 会比你的玩具示例中高很多(在你的示例中添加 10 个不包含“fox”的文档,并且“fox”不会被降权)。
      • 谢谢@mcoav。我已经实现了一个解决方案,它是 tf*df 的总和——它将术语频率计数乘以文档频率计数。任何想法,如果这好还是不好?我根本没有使用 idf,因为我没有停用词,而且经常出现的术语很重要,因此无需更改它们的权重。
      • 我不认为乘以 DF(与仅使用 TF 相比)在这一点上会有所帮助,因为 TF 已经强调了常用词,那么再次确保最好的方法是尝试两种方法。
      【解决方案4】:

      当我在 df-idf 上搜索时,我什么也没找到。

      tf-idfcosine similarity 是非常普遍的做法

      过滤掉停用词并不会破坏它。对于常用词,idf 无论如何都会赋予它们较低的权重。

      tf-idf 被Lucene使用。

      不明白为什么要在这里重新发明轮子。

      不明白为什么你认为 df idf 的总和是一种相似性度量。

      对于分类,您是否有一些预定义的类和示例文档可供学习?如果是这样可以使用Naive Bayes。使用 tf-idf。

      如果您没有预定义的类,您可以使用k means clustering。使用 tf-idf。

      这在很大程度上取决于您对语料库和分类目标的了解。在提供给您的类似诉讼支持文件中,您有并且不知道。在安然,他们用猛禽的名字来形容很多不好的东西,你不可能事先知道。 k 表示让文档找到自己的集群。

      词干并不总能产生更好的分类。如果您以后想要突出显示匹配项,它会变得非常复杂,并且词干不会是单词的长度。

      【讨论】:

      • @AlexOtt 这就是我说 tf-idf 的原因,因为我不确定相似性。我的基本论点仍然相同。遵循标准做法,而不是重新开始。他们不使用 tf-idf 吗?
      【解决方案5】:

      您是否评估过sent2vecdoc2vec 方法?您可以使用向量来查看句子的接近程度。只是一个想法。不是您问题的经过验证的解决方案。

      【讨论】:

        【解决方案6】:

        虽然在英语中一个单词可能就足够了,但在其他一些更复杂的语言中却并非如此。

        一个词有很多含义,也有很多不同的用例。一个文本可以谈论相同的事情,同时使用很少到没有匹配的单词。

        您需要找到文本中最重要的单词。然后你需要抓住他们可能的同义词。

        为此,以下 api 可以提供帮助。用一些字典创建类似的东西是可行的。

        synonyms("complex")
        
        function synonyms(me){
          var url = 'https://api.datamuse.com/words?ml=' + me;
          fetch(url).then(v => v.json()).then((function(v){
            syn = JSON.stringify(v)
            syn = JSON.parse(syn)
            for(var k in syn){
              document.body.innerHTML += "<span>"+syn[k].word+"</span> "
              }
            })
          )
        }

        从那里比较数组将提供更高的准确性,更少的误报。

        【讨论】:

          【解决方案7】:

          一个足够的解决方案,在一个可能类似的任务中:

          • 使用 binary 词袋 (BOW) 方法进行向量表示(常用词的权重不高于很少词的权重),而不是真正的 TF 方法

          • 嵌入“word2vec”方法对序列和距离效应很敏感。根据您的超参数,它可能会产生“猎人看到狐狸”和“狐狸看到跳跃的猎人”之间的差异......所以你必须决定,这是否意味着给你的任务增加噪音 - 或者,或者,仅将其用作所有文本的平均向量

          • 提取高句子内相关性单词(例如,通过使用变量均值归一化余弦相似度)

          • 第二步:使用这个高相关词列表,作为肯定列表,即作为新二元向量化器的新词汇

          这对于第二步余弦比较而言是孤立的有意义的单词 - 在我的情况下,即使对于相当少量的训练文本也是如此

          【讨论】:

            猜你喜欢
            • 2020-08-22
            • 1970-01-01
            • 2017-04-11
            • 2019-03-06
            • 2015-04-06
            • 2011-01-24
            • 1970-01-01
            • 2010-11-04
            • 1970-01-01
            相关资源
            最近更新 更多