I am using sklearn.feature_extraction.FeatureHasher to encode categorical variables for machine learning. My categorical variables are numeric IDs, like 1, 2, 3, 6, 18, 19, 20, ... . In total I have 18,000 unique IDs and the highest ID is 28,000.
I want to hash them to encode them as categories since One-hot encoding is out of the picture as it would create 18,000 columns and my dataset already has 4,000,000 rows and that would be painful.
I can't show my dataframe so I illustrate on a sample dataframe.
from sklearn.feature_extraction import FeatureHasher
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
tmpdf = pd.DataFrame(np.arange(10000), columns=["test"])
produces
test
0 0
1 1
2 2
3 3
4 4
... ...
9995 9995
9996 9996
9997 9997
9998 9998
9999 9999
[10000 rows x 1 columns]
Now if I hash with a dictionary:
H = FeatureHasher(n_features=50, input_type="dict")
cdict = [{str(i) : 1} for i in range(10000)]
arr = H.transform(cdict)
plt.matshow(arr.toarray()[::100], cmap="tab10", vmin=-5, vmax=4)
plt.colorbar(shrink=0.4)
plt.show()
this produces:
If instead I hash with strings:
H = FeatureHasher(n_features=50, input_type="string")
arr = H.transform(tmpdf["test"].astype(str))
plt.matshow(arr.toarray()[::100], cmap="tab10", vmin=-5, vmax=4)
plt.colorbar(shrink=0.4)
plt.show()
I get:
Question:
Why does the output of the string based hashing look so weird? looks like a lot of collisions are happening as a lot of columns remain completely unused... Am I using it wrong? For my task of encoding user IDs, is there a better way to do it?


