我对sckit-learn
相当陌生,并且感到困惑,因为TfidVectorizer
有时会为同一文档返回不同的向量。
我的语料库包含>100个文档。
我正在运行:
vectorizer = TfidfVectorizer(ngram_range=(1, 2), token_pattern=r'bw+b', min_df=1)
X = vectorizer.fit_transform(corpus)
初始化TfidVectorizer
并将其调整到语料库中的文档。 corpus
是文本字符串的列表。
之后,如果我这样做:
test = list(vectorizer.transform([corpus[0]]).toarray()[0])
test == list(X.toarray()[0])
结果是 False
.
如果我分别打印list(X.toarray()[0])
和test
的前 20 项,你可以看到它们偏离了一小部分,而我希望它们是相同的。
[0.16971458376720741, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
与。
[0.16971458376720716, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
但如果我这样做:
test_1 = list(vectorizer.transform([corpus[0]).toarray()[0])
test_2 = list(vectorizer.transform([corpus[0]).toarray()[0])
test_1 == test_2
结果是 True
.上面,我基本上计算了两次向量,这就是我认为我在第一个示例中所做的(因为 X 保存了fit_transform
期间返回的向量)。
为什么在我的第一个例子中,向量不同?我在这里做错了什么吗?
正如评论中提到的,这很可能是一个舍入错误,可能不值得担心。
然而,我认为值得尝试理解这种现象。
可能发生的是舍入误差。有时会发生这些错误,因为计算机上的数字不是无限精确的:典型的numpy浮点数将存储在64位上。
它们具有有限精度的事实意味着加法不再是结合的:a + (b + c) 并不总是精确地 (a + b) + c。
让我们尝试在实际中展示此行为:
import numpy as np
a = np.random.random(size=1000000)
print(a.dtype)
print("%.15f" % a.sum())
b = np.random.permutation(a)
print("%.15f" % b.sum())
输出:
float64
500399.674621732032392
500399.674621731741354
现在,如果我们扩展上面的脚本以尝试使用 32 位上的浮点数:
a = a.astype(np.float32)
print(a.dtype)
print("%.15f" % a.sum())
b = np.random.permutation(a)
print("%.15f" % b.sum())
我们得到:
float64
500214.871674167399760
500214.871674167283345
float32
500214.937500000000000
500215.000000000000000
您可以看到误差要高得多:这是因为 32 位上的浮点数不如 64 位上的浮点数精确。
现在,如果您认为这很棒并且想知道更多,numpy 会通过 np.finfo
函数为您提供有关存储浮点数的详细信息:
In [10]: np.finfo(np.float32)
Out[10]: finfo(resolution=1e-06, min=-3.4028235e+38, max=3.4028235e+38, dtype=float32)
对不起,我没有;)回答你的问题。也许您案例中错误的原因并不完全是我解释的,我写这篇文章是因为我认为如果您熟悉这些错误,您就不会首先问这个问题。
希望这无论如何都有帮助!