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

时间:2013-10-19 14:01:12

标签: machine-learning classification scikit-learn tf-idf

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

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

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

这是问题所在,假设我将此F水平叠加到X,因此X将变为1000 x 15015,这会引入一些问题: 1)前15个功能现在扮演的角色很小; 2)内存不足;

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

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

谢谢。

3 个答案:

答案 0 :(得分:8)

  1. 提取词袋(tf-idf)功能,调用这些X_tfidf

  2. 提取元数据功能,调用这些X_metadata

  3. 将它们堆叠在一起:

    X = scipy.sparse.hstack([X_tfidf, X_metadata])
    
  4. 如果它无法按预期工作,请尝试重新规范化:

    from sklearn.preprocessing import normalize
    X = normalize(X, copy=False)
    
  5. 如果您使用LinearSVCLogisticRegressionSGDClassifier等线性估算器,则不必担心功能在分类中的作用;这是估算师的工作。线性估算器为每个单独的特征赋予权重,告诉他们该特征的信息量,即他们为您解决这个问题。

    (非参数,基于距离/相似性的模型,如内核SVM或k-NN,可能会在这些数据集上花费更多时间。)

答案 1 :(得分:3)

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

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

特定方法的选择是特定于问题的,但正如您所看到的 - 有很多可能性,并且不可能只选择“最好的”。

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

答案 2 :(得分:0)

可能的解决方案是使用sklearn.decomposition.NMF等主题模型执行X_tfidf的语义投影。

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

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

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)的主题模型在文本分类中很常见。