为什么 vectorizer.fit_transform(x).astype('bool') 与 vectorizer.set_params(binary=True).fit_transform(x) 不同?

Eri*_*Taw 4 python scikit-learn

这是我正在谈论的一个最小的例子:

import numpy as np
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer

data = fetch_20newsgroups()
x = data.data

vec = TfidfVectorizer(min_df=0.01, max_df=0.5)
mat = vec.fit_transform(x).astype('bool')

vec.set_params(binary=True)
print(np.array_equal(mat, vec.fit_transform(x)))
Run Code Online (Sandbox Code Playgroud)

这打印False. 设置binary=True和设置所有非零值之间的根本区别是什么True

编辑:正如@juanpa.arrivillaga 所回答,TfidfVectorizer(binary=True)仍然进行逆文档频率计算。但是,我也注意到CountVectorizer(binary=True)不会产生与两者相同的输出.astype('bool')。下面是一个例子:

In [1]: import numpy as np
   ...: from sklearn.datasets import fetch_20newsgroups
   ...: from sklearn.feature_extraction.text import CountVectorizer
   ...:
   ...: data = fetch_20newsgroups()
   ...: x = data.data
   ...:
   ...: vec = CountVectorizer(min_df=0.01, max_df=0.5)
   ...: a = vec.fit_transform(x).astype('bool')
   ...:
   ...: vec.set_params(binary=True)
   ...: b = vec.fit_transform(x).astype('bool')
   ...: print(np.array_equal(a, b))
   ...:
False

In [2]: a
Out[2]:
<11314x2141 sparse matrix of type '<class 'numpy.bool_'>'
        with 950068 stored elements in Compressed Sparse Row format>

In [3]: b
Out[3]:
<11314x2141 sparse matrix of type '<class 'numpy.bool_'>'
        with 950068 stored elements in Compressed Sparse Row format>
Run Code Online (Sandbox Code Playgroud)

维度和 dtype 是相同的,这让我相信这些矩阵的内容是不同的。仅通过观察print(a)and的输出print(b),它们看起来是一样的。

jua*_*aga 5

你从根本上混淆了两件事。

一种是转换为布尔 numpy 数据类型,它等效于接受两个值 True 和 False 的 python 数据类型,除了它在底层原始数组中表示为单个字节。

binary参数传递给TfidfVectorizer数据建模的方式会发生变化。简而言之,如果您使用binary=True,总计数将是二进制的,即可见或不可见。然后你做通常的 tf-id 转换。从文档

如果为 True,则所有非零项计数都设置为 1。这并不意味着输出将只有 0/1 值,只是 tf-idf 中的 tf 项是二进制的。(将 idf 和归一化设置为 False 以获得 0/1 输出。)

所以你甚至没有得到一个布尔输出。

所以考虑:

In [10]: import numpy as np
    ...: from sklearn.feature_extraction.text import TfidfVectorizer
    ...:

In [11]: data = [
    ...:     'The quick brown fox jumped over the lazy dog',
    ...:     'how much wood could a woodchuck chuck if a woodchuck could chuck wood'
    ...: ]

In [12]: TfidfVectorizer().fit_transform(data).todense()
Out[12]:
matrix([[ 0.30151134,  0.        ,  0.        ,  0.30151134,  0.30151134,
          0.        ,  0.        ,  0.30151134,  0.30151134,  0.        ,
          0.30151134,  0.30151134,  0.60302269,  0.        ,  0.        ],
        [ 0.        ,  0.45883147,  0.45883147,  0.        ,  0.        ,
          0.22941573,  0.22941573,  0.        ,  0.        ,  0.22941573,
          0.        ,  0.        ,  0.        ,  0.45883147,  0.45883147]])

In [13]: TfidfVectorizer().fit_transform(data).todense().astype('bool')
Out[13]:
matrix([[ True, False, False,  True,  True, False, False,  True,  True,
         False,  True,  True,  True, False, False],
        [False,  True,  True, False, False,  True,  True, False, False,
          True, False, False, False,  True,  True]], dtype=bool)
Run Code Online (Sandbox Code Playgroud)

现在请注意, usinbinary仍将返回浮点类型:

In [14]: TfidfVectorizer(binary=True).fit_transform(data).todense()
Out[14]:
matrix([[ 0.35355339,  0.        ,  0.        ,  0.35355339,  0.35355339,
          0.        ,  0.        ,  0.35355339,  0.35355339,  0.        ,
          0.35355339,  0.35355339,  0.35355339,  0.        ,  0.        ],
        [ 0.        ,  0.37796447,  0.37796447,  0.        ,  0.        ,
          0.37796447,  0.37796447,  0.        ,  0.        ,  0.37796447,
          0.        ,  0.        ,  0.        ,  0.37796447,  0.37796447]])
Run Code Online (Sandbox Code Playgroud)

它只是改变了结果。