spectral hashing--谱哈希源码解析

论文里面看到了谱哈希用来找子集的用处,不管有没有用,先转再说

原文地址:http://blog.sina.com.cn/s/blog_67914f290101d2xp.html

最近看了有关谱哈希的一些东西,记录一下备忘。理解十分粗浅,敬请各位大牛指导。

一、基本概念
      语义哈希(semantic hashing)是为每个对象(图像或文本)寻找一种二进制编码,使两个对象的相似度与其编码之间的海明距离相关(即相似度高的对象对应的编码海明距离小,相似度低的对象对应的编码海明距离大)。而为每个对象寻找这么一个最优化的编码是NP难解问题,通过松弛优化条件,得到一种谱问题,这个问题的结果是拉普拉斯算子的特征向量的一个子集。这种对松弛后问题的解决方法就是谱哈希。

二、计算编码
      好的编码要满足以下条件:容易计算;短但能表示整个数据集;其海明距离与原对象之间的相似度相关。
      松弛后谱问题的结果是带权拉普拉斯-贝尔特拉米算子的特征方程,通过构造这样的特征方程,并计算其前k个最小的特征值,最后所得到的编码与特征值相关。
      整个过程涉及比较高级的数学知识,超过了我的知识范围,因此理解的十分粗浅。

三、源码分析
      PDF和源码的下载地址: http://www.cs.huji.ac.il/~yweiss/SpectralHashing/
      源码中与谱哈希相关的主要有以下几个文件:trainSH.m,compressSH.m,distMat.m,hammingDist.m,evaluation.m。下面一一介绍。
      1、trainSH.m。输入数据矩阵(每一行代表一个点),通过训练得到谱哈希中所需的若干参数,包括对数据矩阵的PCA(主成分分析)处理及生成特征方程。
         主成分分析是一种对数据降维的方法,减少数据量的同时能尽量避免有用信息的流失。对一个矩阵提取主成分,即对矩阵中的每一行对应的向量提取主成分(对一个数据矩阵,每一行即每一数据点可看做所有随机变量的一次取值,而每一列即每一维可看做一个随机变量),只看矩阵中的其中一行,不妨设第一行,其元素值为x1,x2,…,xd,则其主成分是d个随机变量的一个线性组合,即ai1x1+ai2x2+…+aidxd,而ai1,ai2,…,aid是随机变量X1,X2,…,Xd的相关矩阵的第i个特征向量。因此,计算矩阵X的协方差矩阵(矩阵X有d列,代表d维,也代表d个随机变量,协方差矩阵中元素即是d个随机变量两两之间的协方差)Cov,矩阵Cov为d*d矩阵,计算矩阵Cov的特征向量和特征值,并从大到小取出前k个特征值对应的特征向量组成变换矩阵T,T为d*k矩阵,计算X*T,即提取出X的前k个主成分,因为X*T是s*k矩阵(s为矩阵X原先的长度),故X由原先的d维降到了k维,并且这k维包含了X最多的信息。
         原文中说选取了从小到大的k个特征值,而源码实现中选取了从大到小的k个特征值,源码实现中应该是正确的选择,也许我对原文理解有误,如果有熟悉谱哈希的,希望同志们能留言相告。

      2、compressSH.m。输入数据矩阵和参数(来自trainSH.m的输出),输出U和B。U是k个特征方程的值,是个s*k的矩阵,每一行代表一个数据点,每一列代表一个特征方程的值(用来生成二进制编码)。B是s*ceil(k/8)的矩阵,其中B(i,j)的值等于矩阵U的第i行的第(j-1)*8+1到第j*8个元素(如j=1,则是第1到第8个元素,j=2,则是第9到第16个元素,以此类推)的压缩十进制值。即先将矩阵U的元素按其正负转换成1和0(正对应1,负对应0),然后将8个01值转换成十进制,即得到B中的元素值,8个01值中,维度较低的值处于低位,维度高的值处于高位。比如U的第一行的前八个数为:1,-0.7,-0.5,1,0.3,-0.4,0.2,1,转换后为10011011,左边为低位,右边为高位,转换成十进制数位217,则B(1,1)=217。

      3、hammingDist.m。输入B1,B2(compressSH.m的输出),设B1为s1*ceil(k/8)矩阵,B2为s2*ceil(k/8)矩阵,则输出为s1*s2矩阵D,其中D(i,j)为B1第i行与B2第j行的海明距离(D=compressDist(B1,B2))。设B1第1行为12 14,B2第2行为23 41,则B1第1行转换为二进制为0000110000001110,B2第2行转换为二进制为00010111001 01001,其海明距 8,则D(1,2)=8。

      4、distMat.m。输入为两个矩阵或一个矩阵。若输入两个矩阵,计算两个矩阵两两行之间的欧式距离;若是一个矩阵,计算该矩阵中两两行之间的欧式距离。输入一个矩阵即为输入两个相同矩阵,下只考虑输入为两个矩阵。设这两个矩阵为M1和M2,M1为s1*d矩阵,M2为s2*d矩阵,则输出的距离矩阵D为s1*s2矩阵,其中D(i,j)为M1第i行和M2第j行的欧式距离(l2准则下的欧式距离)。

      5、evaluation.m。这里面包括确定kNN问题中的k值(即距离为k以内的点方视为近邻),及对查询集计算其查准率与查全率。首先对训练集(数据集)进行训练,设训练集为矩阵M,计算distMat(M)得到矩阵D,矩阵D中第i行各元素表示M中第i行与其余各行之间的欧式距离。对D按行进行排序,并求出某选定列的平均值作为近邻查询的半径。若选定第3列,因为第3列的各值表示全部数据集中每一点与其他各点的欧式距离的第三小值,因此可以将此值作为要平均查找3个近邻时所需的半径阈值。返回的查全率(recall)与查准率(precision)均是n*1矩阵,其中n在程序中定义,recall和precision中的第i行表示查找海明距离小于i的点作为候选点,在选出的候选点集中计算对应的查全率与查准率。evaluation.m中第24行中:score = zeros(20,1),即初始n设置为20,用户可以根据自己数据的特点进行修改。

      6、Demo。写Demo的步骤如下:
           (1)利用训练集及要查找的平均近邻数确定可视为近邻的最大距离(确定True Neighbor)。
           (2)计算查询集中每个查询子与所有点之间的距离,并得到一个近邻矩阵N。N(i,j)为1表明第i个查询子与第j个数据点是True Neighbor,为0表示不是True Neighbor。该矩阵用于计算spectral hashing查询结果的recall和precision值。
           (3)利用spectral hashing算法为每个数据点分配二进制编码,并计算查询子与各数据点之间的海明距离。
           (4)定义确定候选集的阈值,N=该阈值内查找到的所有点数(候选集点数),n=候选集中是True Neighbor的点数,M=所有查询子的True Neighbor点数。则recall=n/M,precision=n/N(查全率与查准率的宏观值)。
           这个并不是绝对的,根据自己的实际情况来写。

四、注意
            因为在谱哈系松弛过程中有数据点符合均匀分布的假设,因此这种方法不适用于维度通常很高并且数据矩阵特别稀疏的文本查询。普通文本集都具有数万至数百万级别的维度,并且数据矩阵极为稀疏,这种数据集应用谱哈系所得结果会很差,而如果要得到较好的结果,只能对其进行预降维,这样会损失很多信息,也不会得到特别好的结果。因此,谱哈系通常更适用于图像检索。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值