基于词表的特征向量化
分类问题中,一种常见的方法是构造一个特征词典,如文本分类,会给每个词(可能还有ngram,词性等)设置一个feature_id(向量化(vectorize)
),并记录在一个词典({feature: feature_id})里,从而抽取特征权重的过程通常是这样的:text => feature => feature_id => feature_value
其中第二步的空间复杂度是 O ( d ) \mathcal{O}(d) O(d), d d d是词典的大小,会有这样的问题:
- 训练时需要把词典提前准备好,包括确定维数 d d d和特征的顺序(id),这样就要求需要提前做一次遍历
- 扩展性差:当引入新数据时,如果存在新特征,需要重新设定特征维度和词表,无法做到online learning,也不利于并行训练时的同步
- 对于邮件过滤这类问题,攻击者可以采用新词(如:异体字,火星文),这些对于模型来说就是unknown特征,而模型可能不会激进地标为垃圾邮件
- 当特征维度非常大时,词表也变得很大,导致查找速度显著下降,甚至加载不进内存
特征哈希
考虑到以上的问题,以下paper中介绍了一种方法,叫做特征哈希(Feature Hashing/Hashing trick)
Feature Hashing for Large Scale Multitask Learning
具体方法如下:
def feature_hashing(features, m):
"""
Args:
features: 输入特征序列,可以是数字,字符串(本质还是数字)
m: 输出的特征维度,通常是2**26(vw),2**20(scikit-learn)
Returns:
m维的(稀疏)向量
"""
# 这里的x一般是稀疏表示的(如:scipy.sparse.csr_matrix),这里是为了方便说明
x = np.zeros(m)
for feature in features:
idx = hash_func_1(feature) % m
sign = hash_func_