【问题标题】:TfIdfVectorizer: How does the vectorizer with fixed vocab deal with new words?TfIdfVectorizer:固定词汇的向量器如何处理生词?
【发布时间】:2017-06-23 10:27:05
【问题描述】:

我正在处理大约 10 万篇研究论文的语料库。我正在考虑三个领域:

  1. 纯文本
  2. 标题
  3. 摘要

我使用 TfIdfVectorizer 来获取纯文本字段的 TfIdf 表示,并将由此产生的词汇反馈到标题和摘要的矢量化器中,以确保所有三种表示都在同一个词汇上工作。我的想法是,由于明文字段比其他两个字段大得多,它的词汇很可能会涵盖其他字段中的所有单词。但如果不是这样,TfIdfVectorizer 将如何处理新词/标记?

这是我的代码示例:

vectorizer = TfidfVectorizer(min_df=2)
plaintexts_tfidf = vectorizer.fit_transform(plaintexts)
vocab = vectorizer.vocabulary_
# later in an another script after loading the vocab from disk
vectorizer = TfidfVectorizer(min_df=2, vocabulary=vocab)
titles_tfidf = vectorizer.fit_transform(titles)

这个词汇有大约 90 万个单词。

在矢量化期间我没有遇到任何问题,但后来当我想使用 sklearn.metrics.pairwise.cosine_similarity 比较矢量化标题之间的相似度时,我遇到了这个错误:

>> titles_sim = cosine_similarity(titles_tfidf)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-237-5aa86fe892da> in <module>()
----> 1 titles_sim = cosine_similarity(titles)

/usr/local/lib/python3.5/dist-packages/sklearn/metrics/pairwise.py in cosine_similarity(X, Y, dense_output)
    916         Y_normalized = normalize(Y, copy=True)
    917 
--> 918     K = safe_sparse_dot(X_normalized, Y_normalized.T, dense_output=dense_output)
    919 
    920     return K

/usr/local/lib/python3.5/dist-packages/sklearn/utils/extmath.py in safe_sparse_dot(a, b, dense_output)
    184         ret = a * b
    185         if dense_output and hasattr(ret, "toarray"):
--> 186             ret = ret.toarray()
    187         return ret
    188     else:

/usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py in toarray(self, order, out)
    918     def toarray(self, order=None, out=None):
    919         """See the docstring for `spmatrix.toarray`."""
--> 920         return self.tocoo(copy=False).toarray(order=order, out=out)
    921 
    922     ##############################################################

/usr/local/lib/python3.5/dist-packages/scipy/sparse/coo.py in toarray(self, order, out)
    256         M,N = self.shape
    257         coo_todense(M, N, self.nnz, self.row, self.col, self.data,
--> 258                     B.ravel('A'), fortran)
    259         return B
    260 

ValueError: could not convert integer scalar

我不确定这是否相关,但我真的看不出这里出了什么问题。也因为我在计算明文向量的相似度时没有遇到错误。

我错过了什么吗?有没有更好的方法来使用 Vectorizer?

编辑:

稀疏的 csr_matrices 的形状是相等的。

>> titles_tfidf.shape
(96582, 852885)
>> plaintexts_tfidf.shape
(96582, 852885)

【问题讨论】:

  • 这也是我的第一个想法,但是稀疏 csr_matrices 的尺寸是相等的:plaintexts_tfidf.shape (96582, 852885)titles_tfidf (96582, 852885)

标签: python scikit-learn tf-idf cosine-similarity


【解决方案1】:

恐怕矩阵可能太大了。它将是 96582*96582=9328082724 个单元格。尝试切片titles_tfidf 并检查。

来源:http://scipy-user.10969.n7.nabble.com/SciPy-User-strange-error-when-creating-csr-matrix-td20129.html

美国东部时间: 如果您使用的是旧 SciPy/Numpy 版本,您可能需要更新:https://github.com/scipy/scipy/pull/4678

EDT2: 此外,如果您使用的是 32 位 python,切换到 64 位可能会有所帮助(我想)

EDT3: 回答你原来的问题。当您使用来自plaintexts 的词汇并且titles 中会有新词时,它们将被忽略 - 但不会影响 tfidf 值。希望这个 sn-p 可以使它更容易理解:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

plaintexts =["They are", "plain texts texts amoersand here"]
titles = ["And here", "titles ", "wolf dog eagle", "But here plain"]

vectorizer = TfidfVectorizer()
plaintexts_tfidf = vectorizer.fit_transform(plaintexts)
vocab = vectorizer.vocabulary_
vectorizer = TfidfVectorizer(vocabulary=vocab)
titles_tfidf = vectorizer.fit_transform(titles)
print('values using vocabulary')
print(titles_tfidf)
print(vectorizer.get_feature_names())
print('Brand new vectorizer')
vectorizer = TfidfVectorizer()
titles_tfidf = vectorizer.fit_transform(titles)
print(titles_tfidf)
print(vectorizer.get_feature_names())

结果是:

values using vocabulary
  (0, 2)        1.0
  (3, 3)        0.78528827571
  (3, 2)        0.61913029649
['amoersand', 'are', 'here', 'plain', 'texts', 'they']
Brand new vectorizer
  (0, 0)        0.78528827571
  (0, 4)        0.61913029649
  (1, 6)        1.0
  (2, 7)        0.57735026919
  (2, 2)        0.57735026919
  (2, 3)        0.57735026919
  (3, 4)        0.486934264074
  (3, 1)        0.617614370976
  (3, 5)        0.617614370976
['and', 'but', 'dog', 'eagle', 'here', 'plain', 'titles', 'wolf']

注意它不一样,因为我会从标题中删除明文中没有出现的单词。

【讨论】:

  • 谢谢!将稀疏矩阵转换为密集矩阵似乎也是一种解决方法。幸好我有很多记忆。你对我的第一个问题有什么想法吗,向量化器在第一种情况下如何处理未知单词?
猜你喜欢
  • 2021-08-02
  • 2017-04-01
  • 2020-06-04
  • 2019-07-08
  • 2017-02-11
  • 2020-07-31
  • 1970-01-01
  • 2018-08-21
  • 2013-02-05
相关资源
最近更新 更多