一.题外话
虽然是科普,不过笔者个人认为大道至简,也就是说越简单的东西很可能越值得探讨,或者另外一种说法越简单的东西越不好讲解;其实笔者认为这就是《编程之美》所要传递的——大道至简。
软件构建老师给我推荐的《走出软件作坊》还没看呢。
二.概述
高维数据检索(high-dimentional retrieval)是一个有挑战的任务。对于给定的待检索数据(query),对数据库中的数据逐一进行相似度比较是不现实的,它将耗费大量的时间和空间。这里我们面对的问题主要有两个,第一,两个高维向量的相似度比较,第二,数据库中庞大的数据量。最终检索的复杂度是由这两点共同决定的。
针对第一点,人们开发出很多hash算法,对原高维数据降维。针对第二点,我们希望能在检索的初始阶段就排除一些数据,减小比较的次数。而LSH局部敏感哈希算法恰好满足了我们的需求。其基本思想如下:
假设原数据库中某个高维向量x,维数为n。对其进行汉明化操作,得到n维的二值向量x'。定义m个hash函数,每个hash函数抽取二值向量x'中的k位作为哈希值,这样每个原始高维数据x就会对应m个k位的二值向量。然后,对数据库中的所有原始向量,如果它们对某个具体的哈希函数具有相同的哈希值,那么就把它们放入一个“篮子”里。这里的“篮子”具有两个属性,一是它所属于的hash函数,二是它所对应的哈希值,也就是说,对于两个高维向量x和y来说,只有它们对于同一个hash函数具有相同响应的时候,才会被投入相同的“篮子”中。
这样,我们的检索过程也变得清晰明了。对于待检索向量q,在将其汉明化之后,计算其m个hash函数值,然后将每个hash函数值对应的“篮子”中的向量取出来,这样我们得到了m个“篮子”(每个篮子对应一个hash函数),将这m个“篮子”中的向量取并集,得到集合A。从直观上来讲,A中的向量个数一定远远小于原数据库中的向量个数,这时将q与A中向量一一对比,就能得到检索结果。
LSH算法可以看做这样的两步,第一步将与q完全不相关的向量剔除掉,只保留与q相似的概率较大的向量作为待比较向量,第二步就是讲q与剩余向量逐一对比,注意这里我们仍然可以使用现有的一些降维或者哈希算法提高运算效率。
那么,为什么以上的局部敏感哈希算法能够保留与q具有高相似度的向量呢?首先要感谢我们所用的哈希函数的形式,即对于二值向量随机取k位,这样就保证了相似的向量在哈希映射后仍然相似的概率比较大,而这个特点也是“局部敏感哈希算法”中“局部敏感”的意义所在。因此对这个问题,直观上的理解是,如果对于某个哈希函数来说,两个向量具有相同的响应,说明它们在某个概率下是相似的,如果对于m个哈希函数来说,两个向量的响应都相同,就说明它们相似的可能性更大了。
转载至:https://yq.aliyun.com/articles/288711
感谢作者