为什么 word2vec 的性能比 CountVectorizer 和 TfidfVectorizer 都差得多?【文字分类】

数据挖掘 机器学习 文本挖掘 scikit-学习 word2vec
2022-03-10 17:13:10

我正在按照本指南尝试使用上面指南中显示的MeanEmbeddingVectorizerTfidfEmbeddingVectorizer作为输入来创建二进制分类器和多标签分类器。

两个嵌入向量化器都是这样创建的,首先使用gensim库从文档中启动 w2v,然后对文档中的所有给定单词进行向量映射,并通过取与单个单词对应的所有向量的平均值来向量化它们。

这一步完成后,我尝试使用这些嵌入向量器作为几个模型的输入,例如OneVsRestClassifier(SVC)RandomForestClassifierExtraTreesClassifier因此,就指南中显示的内容而言,所有模型的表现都比我的预期差。

这些是每个模型(二元分类器)的准确度:

randomF_countVect: 0.8898
extraT_countVect: 0.8855
extraT_tfidf: 0.8766
randomF_tfidf: 0.8701
svc_tfidf: 0.8646
svc_countVect: 0.8604
ExtraTrees_w2v: 0.7285
ExtraTrees_w2v_tfidf: 0.7241

多标签分类器也产生了类似的结果。

我不确定我做错了什么。

请注意,我正在处理非常小的文档。其中每个文档由短文本(一两个句子)组成,它们是非英语文档。整个文档总共只有 1163 个唯一词。下面是我的代码。有人可以点亮我吗?

Word2vec 启动

model = Word2Vec([my_tokenizer(item) for item in df['text']], size=100, window=5, min_count=1, workers=2)
w2v = {w: vec for w, vec in zip(model.wv.index2word, model.wv.syn0)}

楷模

svc = Pipeline([("count_vectorizer", vectorizer), ("OneVSRest svc linear", OneVsRestClassifier(SVC(kernel='linear')))])
svc_tfidf = Pipeline([("tfidf_vectorizer", tf_vectorizer), ("OneVSRest svc linear", OneVsRestClassifier(SVC(kernel='linear')))])
randomF = Pipeline([("count_vectorizer", vectorizer), ("RandomForestClassifier", RandomForestClassifier(n_estimators=100))])
randomF_tfidf = Pipeline([("tfidf_vectorizer", tf_vectorizer), ("RandomForestClassifier", RandomForestClassifier(n_estimators=100))])
extraT = Pipeline([("count_vectorizer", vectorizer), ("ExtraTreesClassifier", ExtraTreesClassifier(n_estimators=100))])
extraT_tfidf = Pipeline([("tfidf_vectorizer", tf_vectorizer), ("ExtraTreesClassifier", ExtraTreesClassifier(n_estimators=100))])
etree_w2v = Pipeline([("word2vec vectorizer", MeanEmbeddingVectorizer(w2v)), ("word2vec extra trees", ExtraTreesClassifier(n_estimators=100))])
etree_w2v_tfidf = Pipeline([("tfidf word2vec vectorizer", TfidfEmbeddingVectorizer(w2v)), ("tfidf word2vec extra trees", ExtraTreesClassifier(n_estimators=100))])


all_models = [
    ("svc", svc),
    ("svc_tfidf", svc_tfidf),
    ("randomF", randomF), 
    ("randomF_tfidf", randomF_tfidf),
    ("extraT", extraT), 
    ("extraT_tfidf", extraT_tfidf),
    ("etree_w2v", etree_w2v), 
    ("etree_w2v_tfidf", etree_w2v_tfidf)
]
scores = sorted([(name, cross_val_score(model, df['text'], df['product'], cv=kfold).mean()) 
             for name, model in all_models], 
            key=lambda args: -(args[1]))
3个回答

我的猜测是数据集非常小。Word2Vec 将无法在信息有限的嵌入空间中捕获单词关系。尝试在非常大的语料库上训练 word2vec 以获得非常好的词向量,然后再训练分类器可能会有所帮助。

我假设您了解复杂模型(RandomForestClassifier、ExtraTreesClassifier)中的工作原理,而不是过多地谈论它们是如何工作的。我将参考我使用实时数据在 Twitter 情绪挖掘上工作的项目来解释它 主题:三星 Galaxy S8 结果:有多少百分比的推文是正面和负面的。

模型表现不佳可能原因

  1. 正如unaki建议您需要尝试增加语料库的大小,我想再补充一点,即,要使任何模型表现良好,您需要拥有一个巨大的、高质量的语料库

在我预测推文(实时推文)情绪的场景中,我使用了 1.5 GB 的推文,这些推文手动分为正面或负面。我用它来训练我的模型,我可以得到 90% 的准确率(在 10 条推文中,有 9 条被正确分离)。这是一个耗时的过程,但它帮助我获得了良好的结果。

  1. 正如您所提到的,您有一些不是英语的数据,请确保在给模型之前正确处理这些数据,即,如果您不希望这些词摆脱它们或训练您的模型以理解那些其他语言的词.

在我的场景中,我不得不删除所有非英语,因为我的模型没有经过训练来处理这些单词。我的模型表现良好。准确率提高了 2-3%,这对我来说意义重大。

提高这些模型准确性

现在,为了改进我的模型,我为一些单词制作了一个新字典,例如不太好- 它属于中性情绪(但我没有),如果找到这些单词,那么该推文将被推为负面。通过这种方式,您可以期待更好的情绪隔离。

以同样的方式进行改进,您需要寻找未正确分类的事物(模型错误分类 - 假阳性或假阴性这些术语与混淆矩阵有关)并找到模型遗漏的模式并使用最大化您的模型容量。

检查 fastText 预训练向量 ( https://fasttext.cc/docs/en/crawl-vectors.html ) 以在更大的语料库上生成起点。然后,您可以获取这些向量并使用 gensim 使用您的数据集进一步训练它们。