【问题标题】:How to accurately classify text with a lot of potential values using scikit?如何使用 scikit 对具有大量潜在价值的文本进行准确分类?
【发布时间】:2016-03-10 14:33:48
【问题描述】:

我想在文本段落语料库中识别出各种列入黑名单的术语。每个词大约 1 到 5 个词长,并且包含一些我不希望在我的文档语料库中出现的关键字。如果在语料库中识别出一个术语或类似的东西,我希望将其从我的语料库中删除。

除了删除之外,我正在努力在我的语料库中准确识别这些术语。我正在使用 scikit-learn 并尝试了两种不同的方法:

  1. 一种使用 tf-idf 向量特征的 MultinomialNB 分类方法,混合了列入黑名单的术语和用作训练数据的干净术语。

  2. 一种 OneClassSVM 方法,其中仅将列入黑名单的关键字用作训练数据,传入的任何与列入黑名单的术语不相似的文本都被视为异常值。

这是我的 OnceClassSVm 方法的代码:

df = pd.read_csv("keyword_training_blacklist.csv")

keywords_list = df['Keyword']

pipeline = Pipeline([
    ('vect', CountVectorizer(analyzer='char_wb', max_df=0.75, min_df=1, ngram_range=(1, 5))),
    # strings to token integer counts
    ('tfidf', TfidfTransformer(use_idf=False, norm='l2')),  # integer counts to weighted TF-IDF scores
    ('clf', OneClassSVM(nu=0.1, kernel="rbf", gamma=0.1)),  # train on TF-IDF vectors w/ Naive Bayes classifier
])

kf = KFold(len(keywords_list), 8)
for train_index, test_index in kf:
    # make training and testing datasets
    X_train, X_test = keywords_list[train_index], keywords_list[test_index]

    pipeline.fit(X_train)  # Train classifier using training data and labels
    predicted = pipeline.predict(X_test)
    print(predicted[predicted == 1].size / predicted.size)

csv_df = pd.read_csv("corpus.csv")

testCorpus = csv_df['Terms']

testCorpus = testCorpus.drop_duplicates()


for s in testCorpus:
    if pipeline.predict([s])[0] == 1:
        print(s)

在实践中,当我尝试将我的语料库传递给算法时,我得到了很多误报。我列入黑名单的术语训练数据大约有 3000 个术语。我的训练数据的大小是否需要进一步增加,还是我遗漏了一些明显的东西?

【问题讨论】:

  • 你的实际特征是什么——只是单个词?您是否尝试过使用成对的相邻单词?另外,您所说的“一个术语或与之相似的东西”是什么意思——语义上相似,或者在某个编辑距离内,或者其他什么?
  • 您是否要删除包含这些字词的文档?还是条款本身?你为什么不使用正则表达式?
  • 我想捕捉与我的黑名单中的拼写相似的术语。术语将是一个简单的字符串,例如“这是一个术语”和“loren ipsum”。列入黑名单的术语是“性感女孩”,我想捕捉类似“性感女孩”之类的术语。我查找了诸如 Levenshtein distance 之类的方法,但我不确定它们是否可以包含在 ML 算法中。正则表达式方法起初听起来很明显,但我有数千个列入黑名单的术语和数百万个术语要排序,这解释了我需要 ML 方法。
  • 1) 从 3 个字符开始搜索不超过一定长度的可打印字符 2) 使用这些可打印字符作为新的正则表达式来匹配您当前的字符串列表,从而增加正则表达式的长度在字符串上直到它不再匹配? 3)如果在某个时候它不再与您的字典匹配作为子字符串匹配,则返回到具有最高百分比匹配的最后一个最长字符串并返回值?
  • 您是否先尝试过暴力删除?正则表达式删除或基本 n-gram 匹配。看看需要多长时间。然后找出你的相似性问题。如果 n-gram 匹配工作得相当快(不到一个小时?),那么在该方法之上添加 Levenshtein。为 Levenshtein 设置合适的阈值是经典的精确率、召回率问题。

标签: python machine-learning


【解决方案1】:

尝试使用difflib 来识别语料库中与您列入黑名单的每个术语最接近的匹配项。

import difflib
from nltk.util import ngrams

words = corpus.split(' ') # split corpus to words based on spaces ( can be improved )

words_ngrams = [] # ngrams from 1 to 5 words
for n in range(1,6):
    words_ngrams.extend( ' '.join(ngrams(words, n)) )


to_delete = [] # will contain tuples (index, length) of matched terms to delete from corpus.
sim_rate = 0.8 # similarity rate
max_matches = 4 # maximum number of matches for each term
for term in terms:
    matches = difflib.get_close_matches(term,words_ngrams,n=max_matches,cutoff=sim_rate)
    for match in matches:
        to_delete.append( (corpus.index(match), len(match) ) )

如果您想获得术语和 ngram 之间的相似度分数,也可以使用 difflib.SequenceMatcher

【讨论】:

    猜你喜欢
    • 2019-10-08
    • 2017-08-08
    • 2015-03-16
    • 2015-01-07
    • 2015-02-05
    • 2016-05-16
    • 2017-03-22
    • 2019-09-18
    • 2019-10-07
    相关资源
    最近更新 更多