基于关键词组对文本进行分类?

问题描述 投票:6回答:3

我有一份软件项目的要求清单,由其前身的遗体组装而成。每个要求应映射到一个或多个类别。每个类别都包含一组关键字。我想要做的是找到一个算法,它会给我一个分数排名,每个要求可能属于哪个类别。结果将用作进一步分类要求的起点。

举个例子,假设我有这个要求:

系统应将存款应用于客户的指定帐户。

和类别/关键字:

  1. 客户交易:存款,存款,客户,账户,账户
  2. 余额账户:账户,账户,借方,贷方
  3. 其他类别:foo,bar

我希望算法在类别1中得分最高,在类别2中得分较低,而在类别3中得不到。评分机制与我无关,但需要表达的类别1比第2类更有可能。

我是NLP的新手,所以我有点不知所措。我一直在阅读Python中的自然语言处理,并希望应用一些概念,但没有看到任何非常适合的东西。我认为简单的频率分布不会起作用,因为我正在处理的文本很小(一个句子)。

algorithm nlp text-processing
3个回答
4
投票

您可能希望查看“相似性度量”或“距离度量”的类别(在数据挖掘术语中,与“分类”不同。)

基本上,相似性度量是数学中的一种方式,您可以:

  1. 取两组数据(在你的情况下,单词)
  2. 做一些计算/方程/算法
  3. 结果是你有一些数字告诉你数据是如何“相似”的。

使用相似性度量,此数字是介于0和1之间的数字,其中“0”表示“根本不匹配”,“1”表示“相同”

因此,您实际上可以将您的句子视为向量 - 并且您的句子中的每个单词都代表该向量的元素。同样,对于每个类别的关键字列表。

然后你可以做一些非常简单的事情:取“cosine similarity”或“Jaccard index”(取决于你如何构建你的数据。)

这两个指标的作用是它们采用两个向量(您的输入句子和“关键字”列表)并给出一个数字。如果您在所有类别中执行此操作,则可以对这些数字进行排名,以查看哪个匹配具有最大的相似系数。

举个例子:

从你的问题:

客户交易:存款,存款,客户,账户,账户

因此,您可以构造一个包含5个元素的向量:(1,1,1,1,1)。这意味着,对于“客户交易”关键字,您有5个单词,并且(这听起来很明显但是)每个单词都出现在您的搜索字符串中。跟我一起

所以现在你接受你的判决:

系统应将存款应用于客户的指定帐户。

这有来自“客户交易”集的2个字:{deposit,account,customer}

(实际上,这说明了另一个细微差别:你实际上有“客户”。这相当于“客户”吗?)

你的句子的向量可能是(1,0,1,1,0)

此向量中的1与第一个向量中的1位于同一位置 - 因为这些单词是相同的。

所以我们可以说:这些载体有多少次不同?让我们比较一下:

(1,1,1,1,1) (1,0,1,1,0)

嗯。它们具有相同的“位”3次 - 在第1,第3和第4位置。它们只相差2位。所以我们说当我们比较这两个向量时,我们有一个“距离”2.恭喜,我们只计算了Hamming distance!汉明距离越低,数据越“相似”。

(“相似性”度量与“距离”度量之间的差异在于前者是标准化的 - 它给出的值介于0和1之间。距离只是任意数字,因此它只给出相对值。)

无论如何,这可能不是进行自然语言处理的最佳方式,但对于您的目的而言,它是最简单的,并且实际上可以很好地适用于您的应用程序,或者至少作为起点。

(PS:“分类” - 正如你在标题中所说的那样 - 会回答这个问题“如果你接受我的判决,哪一类最有可能落入?”这与说“多少相似是有点不同”我的第1类比第2类的判决?“这似乎是你所追求的。”

祝好运!


2
投票

该问题的主要特征是:

  • 外部定义的分类标准(关键字列表)
  • 要分类的项目(来自需求文档的行)由相对较少数量的属性值组成,实际上是单个维度:“关键字”。
  • 根据定义,没有反馈/校准(虽然可能适合建议一些)

这些特征带来好消息和坏消息:实施应该相对简单,但分类过程的一致准确性可能难以实现。此外,如果需要,少量的各种数量(可能类别的数量,项目中的最大/平均字数等)应该为我们提供选择可能是CPU和/或空间的解决方案的空间。

然而,即使这个许可证变得“花哨”,我建议从一个简单的算法开始(并保持接近),并在此基础上花费一些补充和考虑,同时保持警惕的过度存在的危险称为过度拟合。

基本算法(概念,即此时不关注性能技巧)

   Parameters = 
     CatKWs = an array/hash of lists of strings.  The list contains the possible
              keywords, for a given category.
         usage: CatKWs[CustTx] = ('deposits', 'deposit', 'customer' ...)
     NbCats = integer number of pre-defined categories
   Variables:
      CatAccu = an array/hash of numeric values with one entry per each of the
                possible categories.  usage:  CatAccu[3] = 4 (if array) or 
                 CatAccu['CustTx'] += 1  (hash)
      TotalKwOccurences = counts the total number of keywords matches (counts
       multiple when a word is found in several pre-defined categories)

    Pseudo code:  (for categorizing one input item)
       1. for x in 1 to NbCats
            CatAccu[x] = 0    // reset the accumulators
       2. for each word W in Item
             for each x in 1 to NbCats
                 if W found in CatKWs[x]
                      TotalKwOccurences++
                      CatAccu[x]++
       3. for each x in 1 to NbCats
             CatAccu[x] = CatAccu[x] / TotalKwOccurences  // calculate rating
       4. Sort CatAccu by value
       5. Return the ordered list of (CategoryID, rating)
              for all corresponding CatAccu[x] values about a given threshold.

简单但似乎合理:我们赞成匹配最多的类别,但我们除以匹配的总数,作为在找到许多单词时降低置信度的方法。请注意,此划分不会影响给定项目的类别选择的相对排名,但在比较不同项目的评级时可能会很重要。

现在,我想到了几个简单的改进:(我认真考虑前两个,并考虑其他的;决定每一个与项目的范围,数据的统计概况非常相关)被分类和其他因素...)

  • 我们应该规范化从输入项中读取的关键字和/或以容忍拼写错误的方式匹配它们。由于我们的言辞很少,我们需要确保我们不会因为愚蠢的错字而失去重要的一句话。
  • 我们应该更加重视在CatKW中发现频率较低的词汇。例如,“帐户”一词应该小于“foo”或“credit”字样
  • 我们可以(但可能没有用,甚至没有帮助)对具有较少[非噪音]单词的项目的评级给予更多权重。
  • 我们还可以包括基于digrams(两个连续的单词)的考虑,对于自然语言(并且需求文档不太自然:-))单词接近度通常是单词本身的更强指示。
  • 我们可以为分配给前一个(甚至后面的,在前瞻逻辑中)项目的类别添加一点点重要性。项目可能会出现在相关系列中,我们可以从这种规律性中受益。

此外,除了计算评级本身外,我们还应考虑:

  • 一些用于评估算法结果本身的指标(tbd)
  • 一些逻辑来收集与指定类别相关联的单词列表,并最终对这些单词运行统计。这可以允许识别代表类别的单词,而不是最初在CatKW中列出的单词。

度量的问题应该尽早考虑,但这也需要输入项的参考集:排序的“训练集”,即使我们正在处理预定义的字典类别 - 关键字(通常使用训练集)确定这个类别关键字的列表,以及权重因子)。当然,这样的参考/训练集应该具有统计显着性和统计学上的[整套]。

总结一下:坚持简单的方法,无论如何,上下文不会留下非常花哨的空间。考虑引入一种测量特定算法(或给定算法中特定参数)效率的方法,但要注意这些指标可能存在缺陷,并提示您在不损害其他项目的情况下专门针对给定集合的解决方案(过度拟合) )。


0
投票

我也面临着仅基于关键字创建分类器的相同问题。我有一个类关键字映射文件,其中包含类变量和特定类中出现的关键字列表。我带来了以下算法,它工作得非常好。

# predictor algorithm
for docs in readContent:
    for x in range(len(docKywrdmppr)):
        catAccum[x]=0
    for i in range(len(docKywrdmppr)):
        for word in removeStopWords(docs):
            if word.casefold() in removeStopWords(docKywrdmppr['Keywords'][i].casefold()):
                print(word)
                catAccum[i]=catAccum[i]+counter
    print(catAccum)
    ind=catAccum.index(max(catAccum))
    print(ind)
    predictedDoc.append(docKywrdmppr['Document Type'][ind])
© www.soinside.com 2019 - 2024. All rights reserved.