FeatureHasher使用方法详解

1. 引入

当我们的原始数据,是字符串,字符串列表,整数列表,pair列表时,都可以使用FeatureHasher转换为特征向量,这又是特征工程中的一个利器。

具体到PE文件分析领域,导入导出表(string list),各种section的size list(int list),都可以使用FeatureHasher来提取特征。

2. FeatureHasher原理简介

从FeatureHasher的出处(参考1),可以知道FeatureHasher是使用Murmurhash3来对输入数据计算hash值。

Murmurhash是一种非加密哈希,所以相似的内容计算出来的hash值(特征向量)也是相似的,所以Murmurhash可以被用于做相似性搜索。

Murmurhash3是Murmurhash家族的一种具体算法,详见参考2。Murmurhash的名字由来,是从参考3中看到,(multiply and rotate) and (multiply and rotate) Hash,乘法和旋转的hash 算法。

3. FeatureHasher用法

从参考1中可知,FeatureHasher输入不同类型的数据,需要配置的就是input_type这个参数,它有三种选择

Choose a string from {‘dict’, ‘pair’, ‘string’}. Either “dict” (the default) to accept dictionaries over (feature_name, value); “pair” to accept pairs of (feature_name, value); or “string” to accept single strings. feature_name should be a string, while value should be a number.

3.1 FeatureHasher输入dict

这是参考1中给定的FeatureHasher的默认用法,具体示例如下

from sklearn.feature_extraction import FeatureHasher
h = FeatureHasher(n_features=10)
# 2 sample as 2 dict
D = [{
    
    'dog': 1, 'cat':2, 'elephant':4},{
    
    'dog': 2, 'run': 5}]
f = h.transform(D).toarray()
print(f)
'''[[ 0.  0. -4. -1.  0.  0.  0.  0.  0.  2.]
 [ 0.  0.  0. -2. -5.  0.  0.  0.  0.  0.]]'''

这里输入两个样本特征,并设置特征向量维度为10,所以最终得到的结果是2x10的array。

3.2 FeatureHasher输入string

输入一个字符串(这里假设输入是’hello’),计算其特征向量的代码如下:

from sklearn.feature_extraction import FeatureHasher
h = FeatureHasher(n_features=10, input_type="string")
D = ['hello']# input one string
f = h.transform(D).toarray()
print(f)# output [[ 0.  0.  2.  1.  0. -1.  0.  0.  0.  1.]]

3.3 FeatureHasher输入string list

如下为输入一个字符串列表,计算得到一个特征向量。

from sklearn.feature_extraction import FeatureHasher
h = FeatureHasher(n_features=10, input_type="string")
D = [['hello','this','is','my code']]
f = h.transform(D).toarray()
print(f)# output [[0. 0. 1. 0. 0. 0. 0. 1. 0. 0.]]

如下为输入多个(两个)字符串列表,计算得到多个(两个)特征向量。

from sklearn.feature_extraction import FeatureHasher
h = FeatureHasher(n_features=10, input_type="string")
# input 2 samples as 2 list of strings
D = [['hello','this','is','my code'],['hello','this','is','my co']]
f = h.transform(D).toarray()
print(f)
#[[0. 0. 1. 0. 0. 0. 0. 1. 0. 0.]
#[0. 1. 1. 0. 0. 0. 1. 1. 0. 0.]]

3.4 FeatureHasher输入int

FeatureHasher输入int数据,用法如下:

from sklearn.feature_extraction import FeatureHasher
h = FeatureHasher(n_features=10, input_type="pair")
D = [[('aaa',777)]]
f = h.transform(D).toarray()
print(f)# [[  0.   0.   0.   0.   0. 777.   0.   0.   0.   0.]]

FeatureHasher本身是不接受int值作为输入的,所以必须转换为tuple,而且tuple第一个数据还必须是字符串,所以还得为这个int值额外插入一个字符串。

这就是参考1中提到的pair输入的要求

  • “pair” to accept pairs of (feature_name, value); or “string” to accept single strings. feature_name should be a string, while value should be a number.
  • tuple的第一个数据,feature_name必须是字符串类型
  • tuple的第二个数据,value必须是int类型

3.5 FeatureHasher输入int list

从上一小节可知,输入为int list时,input_type=“pair”,而且要为每个int值增加feature_name后组成tuple,具体写法如下:

from sklearn.feature_extraction import FeatureHasher
h = FeatureHasher(n_features=10, input_type="pair")
x_list = [4,1,2,7,5]
D = [[('feature_name{0}'.format(i), x_list[i]) for i in range(len(x_list))]]
f = h.transform(D).toarray()
print(f)# [[  0.   0.   0.   0.   0. 777.   0.   0.   0.   0.]]
print(D)# [[('feature_name0', 4),  ('feature_name1', 1),  ('feature_name2', 2),  ('feature_name3', 7),  ('feature_name4', 5)]]

4. FeatureHasher输入特征向量的相似性

用下面两个例子来说明,对于 FeatureHasher,如果输入的内容相似,则最终生成的特征向量也相似。

  1. 输入string list
from sklearn.feature_extraction import FeatureHasher
h = FeatureHasher(n_features=10, input_type="string")
D1 = [['hello','this','is','my code']]
f1 = h.transform(D1).toarray()# [[0. 0. 1. 0. 0. 0. 0. 1. 0. 0.]]
D2 = [['is','this','my code','hello']]
f2 = h.transform(D2).toarray()# [[0. 0. 1. 0. 0. 0. 0. 1. 0. 0.]]
D3 = [['is','this','my cOde','hello']]
f3 = h.transform(D3).toarray()# [[ 0.  1.  1.  0.  0.  0.  0.  1. -1.  0.]]

从结果中可以看到

  • D2和D1内容相似:D2是D1的元素顺序调换,不改变内容,只改变元素顺序,最终结果f2和f1的结果是完全相同的
  • D3和D2内容相似:D3是D2基础上改动了一个字符,最终结果f3也和f2是相似的
  1. 输入int list
from sklearn.feature_extraction import FeatureHasher
h = FeatureHasher(n_features=10, input_type="pair")
x_list1 = [4,1,2,7,5]
D1 = [[('feature_name{0}'.format(x_list1[i]), x_list1[i]) for i in range(len(x_list1))]]
f1 = h.transform(D1).toarray()
x_list2 = [1,7,4,2,5]
D2 = [[('feature_name{0}'.format(x_list2[i]), x_list2[i]) for i in range(len(x_list2))]]
f2 = h.transform(D2).toarray()
x_list3 = [4,1,2,7,9]
D3 = [[('feature_name{0}'.format(x_list3[i]), x_list3[i]) for i in range(len(x_list3))]]
f3 = h.transform(D3).toarray()
print(f1)#[[ 0. -7. -4.  0. -5.  3.  0.  0.  0.  0.]]
print(f2)#[[ 0. -7. -4.  0. -5.  3.  0.  0.  0.  0.]]
print(f3)#[[ 0. -7. -4.  0. -9.  3.  0.  0.  0.  0.]]

可见,list中int值的顺序调换,或者数值有细微的变化,最终生成的特征向量值都是相等/相似的。当然int值比较特殊,这里需要feature_name也相似或不变。

5. 总结

使用FeatureHasher为整数列表,或者字符串列表计算特征向量,是一个比较轻量级(相比于深度学习或者NLP的wordembedding)的特征工程方案。

参考

  1. https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.FeatureHasher.html
  2. https://en.wikipedia.org/wiki/MurmurHash
  3. https://blog.csdn.net/yjgithub/article/details/120447399

猜你喜欢

转载自blog.csdn.net/ybdesire/article/details/128637494