有符号特征哈希:同样发生碰撞,为什么加上负号能让内积无偏

昨天 3阅读

文本分类或在线学习中,特征名可能不断增加。特征哈希把名称直接映射到固定数量的桶,避免维护不断扩大的词典,但不同特征会碰撞。有符号版本额外给每个特征一个固定的正负号。检查这种压缩方法时,最容易混淆的是“平均误差为零”和“这次误差很小”。

有符号特征哈希:同样发生碰撞,为什么加上负号能让内积无偏

AI生成的概念示意图:带正负标记的特征进入共享桶;只是碰撞机制示意,不表示真实误差大小或实验结果。

先固定桶,再算碰撞后的内积

设三个原特征对应向量x=(2,1,0)、y=(0,3,4),真实内积为2×0+1×3+0×4=3。现在把前两个特征都映射到甲桶,第三个映射到乙桶。这里桶的选择是为便于解释而指定的教学设定。

不加符号时,同桶数值相加,x变为(3,0),y变为(3,4),内积变成9。展开第一桶乘积,除了原来已有的1×3,还额外出现2×3=6。它把两个不同特征的数值相乘了,这就是碰撞带来的交叉项。

给三个特征分别指定符号(+1,-1,+1),则x变为(1,0),y变为(-3,4),内积变成-3。与原值3相比,这一次低估了6。负号确实改变了碰撞误差,但没有自动把结果修正回3。

枚举符号,才能看清期望在哪

仍固定上述桶布局,只让三个符号s₁、s₂、s₃各自独立、等概率取正负1,并与桶分配独立。哈希内积可展开为3+6s₁s₂。第三个特征在x中为0,因此s₃不会改变此次内积。

共有八种等可能符号组合,其中四种得到9,另四种得到-3,平均值恰好为3。碰撞误差有正有负,期望抵消;本例的八个单次结果却没有一个等于3。误差平方的平均值为36,也显示了这组极小桶数下的波动。

一般展开式中,同一特征贡献的符号平方为1,保留原内积;不同特征的交叉项,在相互独立且均值为零的随机符号下期望为零。这里的“无偏”针对随机映射取期望。上线后固定了一套映射,并不会随着查询次数增加自行变准。

连向量长度也要用同样的方式检查

x的原长度平方为2²+1²=5。压到甲桶后,它变成(2s₁+s₂)²=5+4s₁s₂,只会得到1或9,均值仍是5。于是内积与长度都可以在期望上保持,同时某次映射仍严重改变几何关系。

如果后面再做长度归一化、余弦相似度或非线性预测,不应直接把内积无偏结论搬过去。分子与分母一起随机变化时,比值的期望通常不能由各自期望相除得到,应针对实际输出重新检查。

工程上保存同一套规则

同一个特征名的桶和符号必须在所有样本间一致。不能在每次遇见该词时重新抽符号,也不能训练时采用一种编码、预测时换另一种。应固定特征名称规范、桶数、哈希算法和版本,让AI用已知小向量检查两端输出。

scikit-learn的FeatureHasher提供alternate_sign参数,官方说明其用途是近似保持哈希空间的内积。若关闭符号以满足某些模型的非负输入要求,就改变了误差机制;本文无偏推导不能继续原样引用。

  • 先记录碰撞特征及其权重,排查少量大权重是否主导误差

  • 在固定验证集上比较多个桶数和独立映射,保留坏案例

  • 明确压缩后通常无法唯一还原原特征,别把共享桶解释成一个具体词

资料核对日期:2026年10月3日。本文使用原创教学向量,Python已枚举八种符号,并额外枚举两个桶的全部分配进行核对,未进行分类训练或真实业务测试。

参考资料

Weinberger等:Feature Hashing for Large Scale Multitask Learning,定义1与引理2

scikit-learn:FeatureHasher参数说明


文章版权声明:除非注明,否则均为云鹊BLOG原创文章,转载或复制请以超链接形式并注明出处。