sklearn FeatureHasher 中的哈希技巧
Hash trick in sklearn FeatureHasher
想了解"the hashing trick"我写了如下测试代码:
import pandas as pd
from sklearn.feature_extraction import FeatureHasher
test = pd.DataFrame({'type': ['a', 'b', 'c', 'd', 'e','f','g','h']})
h = FeatureHasher(n_features=4, input_type='string')
f = h.transform(test.type)
print(f.toarray())
在上面的示例中,我将 8 个类别映射到 4 列,输出为:
[[ 0. 0. 1. 0.]<-a
[ 0. -1. 0. 0.]<-b
[ 0. -1. 0. 0.]<-c
[ 0. 0. 0. 1.]<-d
[ 0. 0. 0. 1.]<-e
[ 0. 0. 0. 1.]<-f
[ 0. 0. -1. 0.]<-g
[ 0. -1. 0. 0.]]<-g
在生成的矩阵中,我可以看到重复项,并且某些类别的表示方式相同。这是为什么?如果我使用二进制表示,8 个类别可以映射到 4 列。
有人可以解释一下这种技术的输出结果并详细说明一下吗?
如果将 设置为如此低的值,FeatureHasher
将导致不希望的结果。这样做的原因是它将类别映射到列索引的方式。
例如,与 CountVectorizer
相反,每个类别都被分配了一个唯一的整数索引,该索引对应于仅按出现顺序排列的列,FeatureHasher
将应用 哈希function 到features 来确定每个类别的列索引。因此,它的主要优点是 提高了速度 。然而,通过将 n_features
限制为如此低的值,散列给定类别的结果可能会导致索引 比集合 n_features
更高,因此,您将得到一个 截断的 特征向量。
我们实际上可以通过重现散列是如何完成的来检查这一点
_hashing_fast
which uses murmurhash3_bytes_s32
生成哈希:
from sklearn.utils.murmurhash import murmurhash3_bytes_s32
raw_X = test['type']
raw_X = iter(raw_X)
raw_X = (((f, 1) for f in x) for x in raw_X)
for x in raw_X:
for f, v in x:
f = f'{f}={v}'
fb = (f).encode("utf-8")
h = murmurhash3_bytes_s32(fb, seed=0)
print(f'{f[0]} -> {h}')
如您所见,它会为 e
和 f
精确地生成较大的哈希值,这些哈希值被截断为对应于 d
:
的较低哈希值
a -> -424864564
b -> -992685778
c -> -1984769100
d -> 728527081
e -> 2077529484
f -> 2074045163
g -> -1877798433
h -> -51608576
想了解"the hashing trick"我写了如下测试代码:
import pandas as pd
from sklearn.feature_extraction import FeatureHasher
test = pd.DataFrame({'type': ['a', 'b', 'c', 'd', 'e','f','g','h']})
h = FeatureHasher(n_features=4, input_type='string')
f = h.transform(test.type)
print(f.toarray())
在上面的示例中,我将 8 个类别映射到 4 列,输出为:
[[ 0. 0. 1. 0.]<-a
[ 0. -1. 0. 0.]<-b
[ 0. -1. 0. 0.]<-c
[ 0. 0. 0. 1.]<-d
[ 0. 0. 0. 1.]<-e
[ 0. 0. 0. 1.]<-f
[ 0. 0. -1. 0.]<-g
[ 0. -1. 0. 0.]]<-g
在生成的矩阵中,我可以看到重复项,并且某些类别的表示方式相同。这是为什么?如果我使用二进制表示,8 个类别可以映射到 4 列。
有人可以解释一下这种技术的输出结果并详细说明一下吗?
设置为如此低的值,FeatureHasher
将导致不希望的结果。这样做的原因是它将类别映射到列索引的方式。
例如,与 CountVectorizer
相反,每个类别都被分配了一个唯一的整数索引,该索引对应于仅按出现顺序排列的列,FeatureHasher
将应用 哈希function 到features 来确定每个类别的列索引。因此,它的主要优点是 提高了速度 。然而,通过将 n_features
限制为如此低的值,散列给定类别的结果可能会导致索引 比集合 n_features
更高,因此,您将得到一个 截断的 特征向量。
我们实际上可以通过重现散列是如何完成的来检查这一点
_hashing_fast
which uses murmurhash3_bytes_s32
生成哈希:
from sklearn.utils.murmurhash import murmurhash3_bytes_s32
raw_X = test['type']
raw_X = iter(raw_X)
raw_X = (((f, 1) for f in x) for x in raw_X)
for x in raw_X:
for f, v in x:
f = f'{f}={v}'
fb = (f).encode("utf-8")
h = murmurhash3_bytes_s32(fb, seed=0)
print(f'{f[0]} -> {h}')
如您所见,它会为 e
和 f
精确地生成较大的哈希值,这些哈希值被截断为对应于 d
:
a -> -424864564
b -> -992685778
c -> -1984769100
d -> 728527081
e -> 2077529484
f -> 2074045163
g -> -1877798433
h -> -51608576