我正在使用 scikit-learn 监督学习方法进行文本分类。我有一个带有输入文本字段及其所属类别的训练数据集。我使用 tf-idf、SVM 分类器管道来创建模型。该解决方案适用于普通测试用例。但是,如果输入的新文本在训练集中具有同义词,则该解决方案无法正确分类。
例如:训练数据中可能存在“run”一词,但如果我使用“sprint”一词进行测试,则该解决方案无法正确分类。
这里最好的方法是什么?在训练数据集中为所有单词添加所有同义词对我来说似乎不是一种可扩展的方法
最佳答案
您应该研究词向量和密集文档嵌入。现在,您正在向 scikit-learn 传递一个矩阵 X
,其中每一行都是数据集中文档的数字表示。您正在使用 tf-idf 获得这种表示,但正如您注意到的那样,这并没有捕捉到单词的相似性,而且您也遇到了词汇量不足的问题。
一个可能的改进是用一个密集的向量来表示每个单词,比如说 300 维,这样具有相似含义的单词在这个 300 维空间中是接近的。幸运的是,您不需要从头开始构建这些向量(查找 gensim word2vec 和 spacy)。另一个好处是,通过使用在非常大的语料库(如维基百科)上预先训练的词嵌入,您将大量关于世界的语言信息整合到您的算法中,否则您无法从您的语料库中推断出这些信息(例如 sprint 和 run是同义词)。
一旦获得了良好的语义数字表示,您就需要为每个文档获得一个向量表示。最简单的方法是对句子中每个词的词向量求平均。
让您入门的示例伪代码:
>>> import spacy
>>> nlp = spacy.load('en')
>>> doc1 = nlp('I had a good run')
>>> doc1.vector
array([ 6.17495403e-02, 2.07064897e-02, -1.56451517e-03,
1.02607915e-02, -1.30429687e-02, 1.60102192e-02, ...
现在让我们尝试不同的文档:
>>> doc2 = nlp('I had a great sprint')
>>> doc2.vector
array([ 0.02453461, -0.00261007, 0.01455955, -0.01595449, -0.01795897,
-0.02184369, -0.01654281, 0.01735667, 0.00054854, ...
>>> doc2.similarity(doc1)
0.8820845113100807
注意向量是如何相似的(在余弦相似度的意义上),即使单词不同。由于向量相似,scikit-learn 分类器将学习将它们分配到相同的类别。对于 tf-idf 表示,情况并非如此。
这是在 scikit-learn 中使用这些向量的方法:
X = [nlp(text).vector for text in corpus]
clf.fit(X, y)
关于machine-learning - 在文本分类的监督学习中解决同义词,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39909928/