You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

基于汉明距离对二进制字符串(模糊哈希)聚类的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

火山引擎 最新活动