我有一份软件项目的要求清单,由其前身的遗体组装而成。每个要求应映射到一个或多个类别。每个类别都包含一组关键字。我正在尝试做的是找到一种算法,它可以给我一个分数排名,每个要求可能属于哪个类别。结果将作为进一步分类要求的起点。
举个例子,假设我有这个要求:
系统应将存款应用于客户的指定账户。
和类别/关键字:
我希望算法在类别1中得分最高,在类别2中得分较低,而在类别3中得不到。评分机制与我无关,但需要表达第1类应用的可能性。比第2类。
我是NLP的新手,所以我有点不知所措。我一直在阅读 Python中的自然语言处理,并希望应用一些概念,但没有看到任何非常适合的东西。我认为简单的频率分布不会起作用,因为我正在处理的文本很小(一句话)。
答案 0 :(得分:4)
您可能希望查看“相似性度量”或“距离度量”的类别(在数据挖掘术语中,与“分类”不同。)
基本上,相似性度量是数学的一种方式:
使用相似性度量,此数字是介于0和1之间的数字,其中“0”表示“根本不匹配”,“1”表示“相同”
因此,您实际上可以将您的句子视为一个向量 - 并且您的句子中的每个单词都代表该向量的一个元素。同样,对于每个类别的关键字列表。
然后你可以做一些非常简单的事情:取“cosine similarity”或“Jaccard index”(取决于你如何构建数据。)
这两个指标的作用是它们同时采用两个向量(您的输入句子和“关键字”列表)并给出一个数字。如果您在所有类别中执行此操作,则可以对这些数字进行排名,以便查看哪个匹配具有最大的相似系数。
举个例子:
从你的问题:
客户交易:存款, 存款,客户,账户,账户
所以你可以构造一个包含5个元素的向量:(1,1,1,1,1)。这意味着,对于“客户交易”关键字,您有5个单词,并且(这听起来很明显但是)每个单词都出现在您的搜索字符串中。跟我一起。
现在你接受你的判决:
系统应将存款应用于a 客户指定的帐户。
这有来自“客户交易”集的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类的句子?“这似乎是你所追求的。”
祝你好运!答案 1 :(得分: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.
简单但似乎合理:我们赞成匹配最多的类别,但我们除以匹配的总数,作为在找到许多单词时降低置信度的方法。请注意,此划分不会影响给定项目的类别选择的相对排名,但在比较不同项目的评级时可能会很重要。
现在,我想到了几个简单的改进:(我认真考虑前两个,并考虑其他的;决定每一个与项目的范围,统计资料的关系非常紧密要分类的数据和其他因素......)
另外,除了计算评级本身外,我们还应该考虑:
度量的问题,应该尽早考虑,但这也需要输入项的参考集:排序的“训练集”,即使我们正在处理预定义的字典类别 - 关键字(通常是培训)集合用于确定这个类别关键字列表以及权重因子。当然,这样的参考/训练集应具有统计学意义和统计学上的[整套]。
总结一下:坚持简单方法,无论如何,上下文不会留下非常花哨的空间。考虑引入测量特定算法效率的方法(或给定算法中的特定参数),但要注意这些指标可能存在缺陷,并提示您专门针对给定集合的解决方案。损害其他项目(过度拟合)。
答案 2 :(得分: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])