基于汉明距离对二进制字符串(模糊哈希)聚类的Python实现及可行性咨询
基于汉明距离的模糊哈希聚类实现方案(Python)
Absolutely! Clustering fuzzy hashes (whether they're binary strings, hex strings, or integers) using Hamming distance is totally feasible in Python—here's a step-by-step breakdown of how to approach it:
1. 先统一输入格式
不管你的模糊哈希是十六进制字符串、二进制字符串还是长整型,第一步必须把它们转换成长度一致的二进制格式(或整数),因为汉明距离要求两个输入的长度必须相同才能计算。
- 十六进制转二进制:先转成整数再转二进制,补前导零到固定长度(比如模糊哈希常用的64位、128位)
- 长整型转二进制:直接转二进制后补前导零对齐长度
- 二进制字符串:检查长度,不足则补零(确保所有输入长度统一)
示例代码:
def normalize_hash(hash_input, target_length=64): # 统一转换为固定长度的二进制字符串,再转整数方便后续计算 if isinstance(hash_input, str): if all(c in '01' for c in hash_input): # 二进制字符串 binary = hash_input.zfill(target_length) elif all(c in '0123456789abcdefABCDEF' for c in hash_input): # 十六进制字符串 binary = bin(int(hash_input, 16))[2:].zfill(target_length) else: raise ValueError("Unsupported string format—only binary/hex allowed") elif isinstance(hash_input, int): # 长整型 binary = bin(hash_input)[2:].zfill(target_length) else: raise TypeError("Unsupported input type—only str/int allowed") if len(binary) != target_length: raise ValueError(f"Hash must fit into {target_length}-bit binary format") return int(binary, 2)
2. 计算汉明距离
汉明距离是两个等长字符串对应位不同的数量,有两种高效计算方式:
方式一:整数异或统计(推荐,速度更快)
把哈希转换成整数后,异或操作会将不同位标记为1,统计1的个数就是汉明距离:
def hamming_distance(i1, i2): return bin(i1 ^ i2).count('1')
方式二:二进制字符串直接对比
如果保留二进制字符串格式,可以直接逐位对比统计差异:
def hamming_distance_str(s1, s2): if len(s1) != len(s2): raise ValueError("Strings must be of equal length") return sum(c1 != c2 for c1, c2 in zip(s1, s2))
3. 选择合适的聚类算法
对于基于汉明距离的聚类,DBSCAN是最适配的选择——它不需要预先指定聚类数量,而是通过设定距离阈值(ε)和最小样本数(min_samples)自动发现聚类,非常适合模糊哈希的场景(相似哈希归为一类,离群哈希单独成类)。
完整实现示例
from sklearn.cluster import DBSCAN import numpy as np # 示例输入:混合类型的模糊哈希 sample_hashes = [ "a3f1b2c4", # 十六进制 "0b10100011111100011011001011000100", # 二进制 0xa3f1b2c5, # 长整型 "a3f1b2c6", "0b11000011101011001010010111001010", 0xc3ac25ca ] # 第一步:统一转换为整数 target_bit_length = 32 normalized_hashes = [normalize_hash(h, target_bit_length) for h in sample_hashes] # 第二步:自定义汉明距离度量函数(适配sklearn的DBSCAN) def hamming_metric(x, y): return bin(int(x[0]) ^ int(y[0])).count('1') # 转换为sklearn要求的格式 X = np.array(normalized_hashes).reshape(-1, 1) # 第三步:运行DBSCAN聚类 # ε:汉明距离阈值,比如设置为2表示距离≤2的哈希归为一类 # min_samples:每个聚类至少包含的样本数 dbscan = DBSCAN(eps=2, min_samples=2, metric=hamming_metric) cluster_labels = dbscan.fit_predict(X) # 输出聚类结果 print("聚类结果:") for idx, label in enumerate(cluster_labels): print(f"哈希 {sample_hashes[idx]} → 聚类ID: {label}")
4. 关键注意事项
- 严格统一长度:所有哈希必须转换为相同长度的格式,否则汉明距离计算无意义
- 阈值调整:ε的设置要结合业务场景——比如模糊哈希(如ssdeep)有自带的相似性标准,可按需调整
- 性能优化:如果哈希数量极大(上万条),直接计算全量距离矩阵会很慢,可以考虑用Ball Tree加速最近邻搜索,不过中等规模数据下DBSCAN配合自定义度量就足够高效
内容的提问来源于stack exchange,提问作者Sneha Reddy




