Locality Sensitive Hash

局部敏感哈希(LSH)是一种高效处理高维数据的索引技术,它能有效克服维度灾难,降低KNN搜索的时间复杂度至亚线性级别。LSH常应用于文本和多媒体的相似性检索中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

局部敏感哈希——Locality Sensitive Hash是一种常见的用于处理高维向量的索引办法。与其它基于Tree的数据结构,诸如KD-Tree、SR-Tree相比,它较好地克服了Curse of Dimension,能够将KNN的时间复杂度缩减到sub-linear。LSH多被用于文本、多媒体(图像、音频)的相似性判断。请看下图:

[img]http://dl.iteye.com/upload/attachment/427612/671ac458-dcde-3b9d-9871-f3a8b830db5f.jpg[/img]

参考上图,如果我们要返回距离中心为r的点,LSH会返回给我们范围更远、更多的点,也就是说,LSH返回的结果会带有一定的false positive。我们或许需要使用linear search进行二次筛选,但这毕竟大大减少了计算的时间。

由此可见,LSH与一般的加密型哈希函数有很大的区别,参见下图:

[img]http://dl.iteye.com/upload/attachment/427637/10cda6ed-4a6a-3469-938d-afb1d185581c.jpg[/img]

一种实现LSH的最简单的方式是采用random bits sampling的方式,即将待索引的多维整型向量转化为0或1的字符串;再采用随机选取其中的K位拼接成新的字符串;最后再采用常规的哈希函数(例如MD5)等算法获取带索引向量的LSH Code。这样的Hash Code有一个特点,就是Hamming Distance相近的两个向量,其冲突的概率越大,即结果相等的可能性越大。为了减少增强KNN搜索的能力,与Bloom Filter类似,采用多个Hash Table增加冲突的概率,参见下图:

[img]http://dl.iteye.com/upload/attachment/427656/fe8b709a-dc7e-3269-8306-5e61e6df333f.jpg[/img]

来看一下LSH的复杂度:

[img]http://dl.iteye.com/upload/attachment/427658/a1489356-e4eb-33ea-afb6-fc7a94102b04.jpg[/img]

可见,与各种其它的数据结构相比,基于lsh的索引结构的query时间复杂度,可以做到与向量维度无关,有效地克服了维度灾难的问题,因此更适合高维向量的索引。

基于LSH实现的图像近似检索,其原理也很类似,如下图所示:


[img]http://dl.iteye.com/upload/attachment/427671/32df8f56-3799-34e1-971a-e1f7e607ef60.jpg[/img]

[img]http://dl.iteye.com/upload/attachment/427673/22bd6ac9-2897-3896-8756-0e04317a9738.jpg[/img]

时间关系,下次有空会把LSH的java implementation放上来。
Locality Sensitive Hashing (LSH)是一种用于近似最近邻搜索的数据结构技术,它通过构造一组哈希函数,使得相似的数据元素有较高的概率被映射到相同的哈希桶中。在Python中实现LSH通常涉及以下几个步骤: 1. **选择合适的哈希函数**:LSH的核心是设计对相似数据“敏感”的哈希函数。常见的LSH函数如随机投影、随机散列函数或SimHash。 - **随机投影**:将高维向量映射到低维空间,比如使用`sklearn`库中的`TruncatedSVD`或`random_projection.GaussianRandomProjection`。 - **SimHash**:生成二进制串,对每个维度,如果数值大于0,则对应的位设为1;否则设为0。这种操作可以用`hashlib`中的`md5`或`sha1`等完成。 2. **构建哈希表**:创建多个哈希表,每个表对应一个哈希函数。对于输入数据,应用哈希函数将其映射到不同的桶中。 3. **查找邻居**:给定一个新的查询点,使用同样的哈希函数计算其哈希值,并在所有相关的哈希表中查找碰撞的点。这些可能是潜在的近邻。 4. **合并结果**:为了提高召回率,可以采用“并集”或“交集”策略来合并多个哈希表的结果,进一步筛选出最有可能的近邻。 ```python from sklearn.random_projection import GaussianRandomProjection import hashlib def lsh_search(data, queries, num_tables, hash_len): # 初始化哈希表列表 hash_tables = [[] for _ in range(num_tables)] # 对数据应用哈希函数并存储到哈希表中 for point in data: hashes = [get_hash(point, hash_func) for hash_func in generate_hash_functions(hash_len)] for table_idx, hash_val in zip(range(num_tables), hashes): hash_tables[table_idx].append((point, hash_val)) # 查找近邻 for query in queries: closest_neighbors = set() for table_idx, table_data in enumerate(hash_tables): candidates = [data_point for data_point, _ in table_data if get_hash(query, hash_func) == hash_val] closest_neighbors.update(candidates) return closest_neighbors # 辅助函数:生成哈希函数 def generate_hash_functions(hash_len): rng = np.random.RandomState(42) return rng.normal(size=(hash_len, data_dim)) # 辅助函数:计算哈希值 def get_hash(vector, projection_matrix): projected_vec = projection_matrix.dot(vector) binary_str = ''.join(str(int(i > 0)) for i in projected_vec) return int(binary_str, 2) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值