2

我正在使用特征散列将字符串变量转换为散列以进行分类。经过一番挖掘,我注意到尽管 MurmurHash3 特征哈希的 R 和 Python 实现(R:FeatureHashing:hashed.model.matrix 和 Python:sklearn.feature_extraction.FeatureHasher),但结果在特征放置位置方面是不同的。我认为 MurmurHash 应该是确定性的,因为当您在同一系统上运行相同的操作时,您会得到相同的结果哈希。但是,在实现之间可能存在种子问题?这给我带来了一个问题,因为我的分类模型(xgboost,我意识到 R 和 Python 之间存在问题)可能在相同数据上产生不同的结果,正如其他人所指出的那样。但是,我似乎已经弄清楚了那部分。

以下是 R 中的代码示例:

library(FeatureHasher)
#create a single-feature dataframe
data_tmp <- data.frame(x=c("A_C","B_D"))

#> data_tmp
#    x
#1 A_C
#2 B_D

#create feature hash.  R by default includes an intercept, so remove that
#with ~x -1
fhash <- hashed.model.matrix(~x -1, data=data_tmp, hash.size=16, create.mapping=TRUE)

as.matrix(fhash)
#     1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#[1,] 0 0 0 0 1 0 0 0 0  0  0  0  0  0  0  0
#[2,] 0 0 0 0 0 0 0 0 0  0  0  1  0  0  0  0

如您所见,R 将“A_C”放在第五列,将“B_D”放在第 12 列。这些情况始终如一地发生。现在让我们在 Python 中运行等效的代码。请注意,在 Python 中有多种输入特征散列的方法,作为 dict 或作为列表的列表。我尝试了几个,他们给了我相同的结果。

from sklearn.feature_extraction import FeatureHasher
import pandas as pd

#create as a list of two single-element lists
data_tmp = [["A_C"],["B_D"]]

#can also do this, does the same thing
#pd.DataFrame(data_tmp)

#set up feature hash with same settings above
feature_hash = FeatureHasher( alternate_sign = False, n_features = 16, input_type="string")
fhash = feature_hash.transform( data_tmp )
fhash.todense()
#matrix([[0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
#        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

在这里,“A_C”和“B_D”不仅映射到与以前不同的索引,而且都映射到同一列。这意味着这个特征发生了冲突,因为值 1 代表不同的特征已经无法区分,这会降低分类器的能力。

我在这里有什么明显的遗漏吗?例如,我看到了这篇文章:Murmur3 hash different result between Python and Java implementation,但我对此知之甚少。我注意到的一件事是,在 R 中,如果您使用 create.mapping 选项然后运行

hash.mapping(fhash)
#xB_D xA_C 
#12    5 

当它打印出来时,它会在字符串之前放置一个“x”(变量名),所以我认为这可能是导致问题的原因。但后来我尝试重新运行上面的 Python 代码,除了

data_tmp = [["xA_C"],["xB_D"]]

但是虽然我得到了与以前不同的结果,但它与 R 的映射不匹配。也许这是 Python 存储变量名的内在因素?在此先感谢,我真的很想弄清楚这一点。

4

0 回答 0