在实践中如何使用 TfidfVectorizer 和元数据进行分类?

Posted

技术标签:

【中文标题】在实践中如何使用 TfidfVectorizer 和元数据进行分类?【英文标题】:How do I do classification using TfidfVectorizer plus metadata in practice? 【发布时间】:2013-10-28 07:30:35 【问题描述】:

我正在尝试将一些文档分为两类,其中我使用 TfidfVectorizer 作为特征提取技术。

输入数据由包含大约十几个浮点数据字段、标签和文档正文的文本块的数据行组成。为了使用主体,我应用了 TfidfVectorizer 并得到了一个稀疏矩阵(我可以通过 toarray() 转换为数组来检查它)。这个矩阵通常非常大,有成千上万的维度——我们称之为 F,它的大小为 1000 x 15000。

为了在 Scikit 中使用分类器,我给它一个输入矩阵 X,它是(行数 * 特征数)。如果我不使用身体,我可能有一个大小为 1000 x 15 的 X。

问题来了,假设我将这个 F 水平叠加到 X 上,所以 X 会变成 1000 x 15015,这就引入了一些问题: 1) 前 15 个功能现在将发挥很小的作用; 2) 内存不足;

Scikit 提供了一个仅使用 TfidfVectorizer 输入的示例,但没有说明如何元数据一起使用它。

我的问题是:如何将 TfidfVectorizer 输出与元数据一起用于训练分类器?

谢谢。

【问题讨论】:

【参考方案1】:

    提取词袋(tf-idf)特征,调用这些X_tfidf

    提取元数据特征,调用这些X_metadata

    将它们堆叠在一起:

    X = scipy.sparse.hstack([X_tfidf, X_metadata])
    

    如果没有按预期工作,请尝试重新规范化:

    from sklearn.preprocessing import normalize
    X = normalize(X, copy=False)
    

如果您使用诸如LinearSVCLogisticRegressionSGDClassifier 之类的线性估计器,则不必担心特征在分类中所起的作用;这是估算员的工作。线性估计器为每个单独的特征分配一个权重,以说明该特征的信息量,即他们会为您计算出来。

(非参数、基于距离/相似性的模型,例如内核 SVM 或 k-NN 可能在此类数据集上比较困难。)

【讨论】:

感谢您的回复。你说得对,我应该把它留给估价员来解决。我会尝试一下,尽管(可能特定于实现),集成(RandomForest,GDT)等似乎不适用于带有错误消息的稀疏矩阵:“传递了稀疏矩阵,但需要密集数据。使用 X .toarray() 转换为密集的 numpy 数组。”,这是一个死胡同,Ogriesel 已经确认 [link]***.com/questions/17184079/… 。 @log0:这是一个已知缺陷。尝试线性模型,或进行一些降维。 所以这是 Scikit Learn 中需要修复的错误?我一直在考虑尝试捡起一些东西来做出贡献,尽管很小...... =] @log0:我们称之为缺失的功能,但它绝对值得实施,欢迎任何帮助。【参考方案2】:

没有将 tf-idf 描述符与其他类型数据合并的通用方法,一切都取决于您的特定模型和数据:

一些模型旨在处理可以具有任意比例的数据,因此 - 它们使用最强的预测变量,无论它们是否只是整个特征向量的 1%。一些决策树信息标准可以是此类方法的一个很好的例子 有些模型可以让您直接“加权”特征以使其比其他模型更重要,因此您可以包含一些专家知识,以便通过例如 N_not_meta/N_meta 比例来加权具有大型非元部分的元数据,其中 N_x 是 x 类型特征维度的数量。 SVM 可以让你做这样的事情,因为它们是尺度相关的线性模型,所以简单的特征重新缩放可以产生这样的效果。此外,在朴素贝叶斯等概率模型中,您可以通过将它们各自的“概率估计”乘以某个预定义因子来强制某些预测变量“强”。 更高级的方法是创建一个分类器集合 - 一个用于元数据,一个用于 tfidf 和一些元分类器(因为 2 个模型的投票方案相当无用)在其输出上进行训练 您还可以通过执行一些降维方法(例如 PCA)来简单地降低第二部分的维度

特定方法的选择与问题密切相关,但正如您所见 - 有很多可能性,不可能简单地选择“最佳方法”。

对于内存不足问题,您应该考虑 scikit-learn 中可用的 sparse 表示。它是 NLP 数据的不错选择,因为文档往往具有非常稀疏的特征向量。

【讨论】:

感谢 Lejlot 的回复。事实上,我没有想过使用两种模型——一种是元数据,一种是实际数据。我会尽量避免进行专家加权,但可能会让估计者弄清楚(集合的集合等)。此外,由于使用了 Scikit-learn,如果我决定使用 RandomForest,它将不适用于稀疏输入,这很可悲。 [***.com/questions/17184079/…【参考方案3】:

一种可能的解决方案是使用诸如sklearn.decomposition.NMF 之类的主题模型执行X_tfidf 的语义投影。

这允许输入稀疏矩阵,并输出一组非稀疏小维的特征。因此,这克服了上面答案中提到的两个问题(稀疏输入和有限的内存)

X_tfidf 向量投影到 20 维特征向量的示例:

nmf = NMF(n_components=20)
nmf.fit(data)
X_transformed = nmf.transform(X_tf_idf)

这里的“数据”是为适合分解模型而给出的任何一组特征(理想情况下,一组保留的特征)。

然后您可以安全地将其与其他功能合并

X = scipy.sparse.hstack([X_transfored, X_metadata])

其他投影是可能的,例如 PCA,但通过矩阵分解的主题模型(例如 NMF 或SVD)在文本分类中很常见。

【讨论】:

以上是关于在实践中如何使用 TfidfVectorizer 和元数据进行分类?的主要内容,如果未能解决你的问题,请参考以下文章

Tfidfvectorizer - 如何查看已处理的令牌?

如何在修剪tfidfvectorizer后检查术语是否为空

如何在 scikit TfidfVectorizer 中赋予专有名词更多的权重

如何从TfidfVectorizer计算余弦相似度?

如何在熊猫数据框上使用 sklearn TFIdfVectorizer

如何在无监督聚类期间在 sklearn 的 TfidfVectorizer 中选择参数