我正在使用scikit-learn监督学习方法进行文本分类。我有一个训练数据集,其中包含输入文本字段及其所属的类别。我使用tf-idf,SVM分类器管道来创建模型。该解决方案适用于正常的测试用例。但是如果输入的新文本与训练集中具有synoynmous单词,则解决方案无法正确分类。 例如:单词' run'可能会出现在训练数据中,但如果我使用“短跑”这个词。为了测试,该解决方案无法正确分类。
这里最好的方法是什么?为训练数据集中的所有单词添加所有同义词并不像我的可扩展方法
答案 0 :(得分:5)
您应该查看单词向量和密集文档嵌入。现在你正在通过scikit-learn一个矩阵X
,其中每一行都是数据集中文档的数字表示。您正在使用tf-idf获得此表示,但是您注意到这并没有捕获单词相似性,并且您也遇到了词汇单词的问题。
一种可能的改进是用一个密集的矢量来表示每个单词,比如尺寸300,这样在这个300维空间中具有相似含义的单词就近了。幸运的是,您不需要从头开始构建这些向量(查找gensim word2vec和spacy)。另一个好处是,通过使用在维基百科等大型语料库中预先训练的单词嵌入,您将大量有关世界的语言信息合并到您的算法中,否则您无法从语料库中推断出(就像sprint这样的事实并且运行是同义词)。
一旦你获得了单词的良好和语义数字表示,你需要获得每个文档的向量表示。最简单的方法是平均句子中每个单词的单词向量。
让你开始的伪代码示例:
>>> 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)