Ха sh трюк в склеарне - PullRequest
       66

Ха sh трюк в склеарне

1 голос
/ 19 апреля 2020

Желая понять «хитрость хеширования», я написал следующий тестовый код:

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 столбца, и вывод: 1004 *

[[ 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 столбца, если я использую двоичное представление.

Может кто-нибудь объяснить, пожалуйста, вывод этой техники и, возможно, немного уточнить?

1 Ответ

1 голос
/ 19 апреля 2020

A FeatureHasher приведет к нежелательным результатам, если вы установите n_features на такое низкое значение. Причиной этого является то, как он отображает категории в индексах столбцов.

В отличие от CountVectorizer, например, когда каждой категории присваивается уникальный целочисленный индекс, соответствующий столбцу только в порядке появления, FeatureHasher будет применять функцию га sh к функциям для определения индекса столбца каждой категории. Следовательно, его главное преимущество - увеличенная скорость . Однако, ограничив n_features таким низким значением, вполне вероятно, что результат хеширования данной категории приведет к тому, что индекс будет выше , чем набор n_features, и, следовательно, вы получите усеченный векторный элемент.


Мы можем фактически проверить это, воспроизведя, как выполняется хеширование в _hashing_fast, который использует 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}')

Что, как вы можете видеть, дает большие значения ha sh точно для e и f, которые усекаются до нижнего значения ha sh, соответствующего до d:

a -> -424864564
b -> -992685778
c -> -1984769100
d -> 728527081
e -> 2077529484
f -> 2074045163
g -> -1877798433
h -> -51608576
...