精华内容
下载资源
问答
  • 敏感数据的安全防范

    2020-04-02 09:42:27
    1、能任意在Cookie、Session、ServletContext中存放数据,对于这些对象中存放的数据,必须有统一定义、说明、Lifecycle的管理等。...为保障这些数据被曝露而提高安全性,我们要做到所有敏感信息必须进行加密处理...

    1、不能任意在Cookie、Session、ServletContext中存放数据,对于这些对象中存放的数据,必须有统一定义、说明、Lifecycle的管理等。

    2、对于敏感信息都必须保障其私密性。

    在页面显示、操作交互中不可避免的会有一些如用户的标识信息、密码、帐号信息、涉及的金额信息等敏感数据(保密性的数据)的存在。为保障这些数据不被曝露而提高安全性,我们要做到所有敏感信息必须进行加密处理,不能以明文的形式存在于任何网络、内存及其它持久化介质中(如:数据库、文件磁盘系统等)。

    3、所有的密码、key、帐号等机密信息都不能在URL中传递。

    4、所有的密码、key、银行账号等机密信息都不能存储到Cookie,Session、ServletContext中。

    5、防止信息泄漏:

    • 在系统上线使用的log level对应的日志输出中不允许包含任何密码、key、账号等机密信息。
    • SVN集成分支上的代码中不允许存留可用的system.out/err.print语句。
    • 在测试/调试阶段所使用的测试页面、单元测试模块等不允许提交到SVN集成分支上。
    • 不允许将系统产生的错误异常信息直接显示给用户,需要有统一的错误处理。

    6、尽量减少不必要的信息传递。

    在信息的传递过程中,如果当前Step中的对象、对象的属性、参数等在下一个Step中不需要,则不要再做传递,甚至可以显式的销毁。这样可以有效的减少信息被截获的机率,特别是敏感数据(例如用户密码、账户信息等等)。

    展开全文
  • 局部敏感哈希

    千次阅读 2016-01-21 22:47:10
    局部敏感哈希 在检索技术中,索引一直需要研究的核心技术。当下,索引技术主要分为三类:基于树的索引技术(tree-based index)、基于哈希的索引技术(hashing-based index)与基于词的倒排索引(visual words ...

    局部敏感哈希

    在检索技术中,索引一直需要研究的核心技术。当下,索引技术主要分为三类:基于树的索引技术(tree-based index)、基于哈希的索引技术(hashing-based index)与基于词的倒排索引(visual words based inverted index)[1]。本文主要对哈希索引技术进行介绍。

    哈希技术概述

    在检索中,需要解决的问题是给定一个查询样本query,返回与此query相似的样本,线性搜索耗时耗力,不能承担此等重任,要想快速找到结果,必须有一种方法可以将搜索空间控制到一个可以接受的范围,哈希在检索中就是承担这样的任务,因而,这些哈希方法一般都是局部敏感(Locality-sensitive)的,即样本越相似,经过哈希后的值越有可能一样。所以,本文中介绍的技术都是局部敏感哈希(Locality Sensitive Hashing,LSH),与hashmap、hashtable等数据结构中的哈希函数有所不同。

    哈希技术分类

    Application_of_LSH

    图 1 LSH分层法使用
    对于哈希技术,可以按照不同的维度对齐进行划分。

    按照其在检索技术中的应用方法来划分,可以分为分层法和哈希码法:

    • 分层法即为在数据查询过程中使用哈希技术在中间添加一层,将数据划分到桶中;在查询时,先对query计算桶标号,找到与query处于同一个桶的所有样本,然后按照样本之间的相似度计算方法(比如欧氏距离、余弦距离等)使用原始数据计算相似度,按照相似度的顺序返回结果,在该方法中,通常是一组或一个哈希函数形成一个表,表内有若干个桶,可以使用多个表来提高查询的准确率,但通常这是以时间为代价的。分层法的示意图如图1所示。在图1中,H1、H2等代表哈希表,g1、g2等代表哈希映射函数。

      分层法的代表算法为E2LSH[2]。

    • 哈希码法则是使用哈希码来代替原始数据进行存储,在分层法中,原始数据仍然需要以在第二层被用来计算相似度,而哈希码法不需要,它使用LSH函数直接将原始数据转换为哈希码,在计算相似度的时候使用hamming距离来衡量。转换为哈希码之后的相似度计算非常之快,比如,可以使用64bit整数来存储哈希码,计算相似度只要使用同或操作就可以得到,唰唰唰,非常之快,忍不住用拟声词来表达我对这种速度的难言之喜,还望各位读者海涵。

      哈希码法的代表算法有很多,比如KLSH[3]、Semantic Hashing[4]、KSH[5]等。

    以我看来,两者的区别在于如下几点:

    • 在对哈希函数的要求上,哈希码方法对哈希函数的要求更高,因为在分层法中,即便哈希没有计算的精确,后面还有原始数据直接计算相似度来保底,得到的结果总不会太差,而哈希码没有后备保底的,胜则胜败则败。
    • 在查询的时间复杂度上,分层法的时间复杂度主要在找到桶后的样本原始数据之间的相似度计算,而哈希码则主要在query的哈希码与所有样本的哈希码之间的hamming距离的相似计算。哈希码法没有太多其他的需要,但分层法中的各个桶之间相对较均衡方能使复杂度降到最低。按照我的经验,在100W的5000维数据中,KSH比E2LSH要快一个数量级。
    • 在哈希函数的使用上,两者使用的哈希函数往往可以互通,E2LSH使用的p-stable LSH函数可以用到哈希码方法上,而KSH等哈希方法也可以用到分层法上去。
      上述的区别分析是我自己分析的,如果有其他意见欢迎讨论。

    按照哈希函数来划分,可以分为无监督和有监督两种:

    • 无监督,哈希函数是基于某种概率理论的,可以达到局部敏感效果。如E2LSH等。
    • 有监督,哈希函数是从数据中学习出来的,如KSH、Semantic Hashing等。

    一般来说,有监督算法比无监督算法更加精确,因而也更常用于哈希码法中。
    本文中,主要对无监督的哈希算法进行介绍。

    Origin LSH

    最原始的LSH算法是1999年提出来的[6]。在本文中称之为Origin LSH。

    Embedding

    Origin LSH在哈希之前,首先要先将数据从L1准则下的欧几里得空间嵌入到Hamming空间。在做此embedding时,有一个假设就是原始点在L1准则下的效果与在L2准则下的效果相差不大,即欧氏距离和曼哈顿距离的差别不大,因为L2准则下的欧几里得空间没有直接的方法嵌入到hamming空间。

    • 找到所有点的所有坐标值中的最大值C;
    • 对于一个点P来说,P=(x1,x2,…,xd),d是数据的维度;
    • 将每一维xi转换为一个长度为C的0/1序列,其中序列的前xi个值为1,剩余的为0.
    • 然后将d个长度为C的序列连接起来,形成一个长度为Cd的序列.

    这就是embedding方法。注意,在实际运算过程中,通过一些策略可以无需将embedding值预先计算出来。

    Algorithm of Origin LSH

    在Origin LSH中,每个哈希函数的定义如下:

    origin_hash

    即输入是一个01序列,输出是该序列中的某一位上的值。于是,hash函数簇内就有Cd个函数。

    在将数据映射到桶中时,选择k个上述哈希函数,组成一个哈希映射,如下:

    k_hash_funcs

    • 从[0,Cd]内取L个数,形成集合G,即组成了一个桶哈希函数g。
    • 对于一个向量P,得到一个L维哈希值,即P|G,其中L维中的每一维都对应一个哈希函数h。
    • 由于直接以上步中得到的L维哈希值做桶标号不方便,因而再进行第二步哈希,第二步哈希就是普通的哈希,将一个向量映射成一个实数。

    hash_to_bucket_id

    其中,a是从[0,M-1]中随机抽选的数字。

    这样,就把一个向量映射到一个桶中了。

    LSH based on p-stable distribution

    该方法由[2]提出,E2LSH[7]是它的一种实现。

    p-stable分布

    定义:对于一个实数集R上的分布D,如果存在P>=0,对任何n个实数v1,…,vn和n个满足D分布的变量X1,…,Xn,随机变量ΣiviXi和(∑i|vi|p)(1/p)X有相同的分布,其中X是服从D分布的一个随机变量,则称D为一个p稳定分布。

    对任何p∈(0,2]存在稳定分布。P=1时是柯西分布;p=2时是高斯分布。

    当p=2时,两个向量v1和v2的映射距离a·v1-a·v2和||v1-v2||pX的分布是一样的,此时对应的距离计算方式为欧式距离。

    利用p-stable分布可以有效的近似高维特征向量,并在保证度量距离的同时,对高维特征向量进行降维,其关键思想是,产生一个d维的随机向量a,随机向量a中的每一维随机的、独立的从p-stable分布中产生。对于一个d维的特征向量v,如定义,随机变量a·v具有和(∑i|vi|p)(1/p)X一样的分布,因此可以用a·v表示向量v来估算||v||p

    E2LSH

    基于p-stable分布,并以‘哈希技术分类’中的分层法为使用方法,就产生了E2LSH算法。

    E2LSH中的哈希函数定义如下:

    k_hash_funcs

    其中,v为d维原始数据,a为随机变量,由正态分布产生; w为宽度值,因为a∙v+b得到的是一个实数,如果不加以处理,那么起不到桶的效果,w是E2LSH中最重要的参数,调得过大,数据就被划分到一个桶中去了,过小就起不到局部敏感的效果。b使用均匀分布随机产生,均匀分布的范围在[0,w]。

    与Origin LSH类似,选取k个上述的哈希函数,组成一个哈希映射,效果如图2所示:

    k_hash_funcs

    图 2 E2LSH映射
    但是这样,得到的结果是(N 1 ,N 2 ,…,N k ),其中N 1 ,N 2 ,…,N k 在整数域而不是只有0,1两个值,这样的k元组就代表一个桶。但将k元组直接当做桶标号存入哈希表,占用内存且不便于查找,为了方便存储,设计者又将其分层,使用数组+链表的方式,如图3所示:

    data_structure_of_e2lsh

    图 3 E2LSH为存储桶标号而产生的数组+链表二层结构
    对每个形式为k元组的桶标号,使用如下h1函数和h2函数计算得到两个值,其中h1的结果是数组中的位置,数组的大小也相当于哈希表的大小,h2的结果值作为k元组的代表,链接到对应数组的h1位置上的链表中。在下面的公式中,r 为[0,prime-1]中依据均匀分布随机产生。

    h1

    h2

    • 对于查询点query,
    • 使用k个哈希函数计算桶标号的k元组;
    • 对k元组计算h1和h2值,
    • 获取哈希表的h1位置的链表,
    • 在链表中查找h2值,
    • 获取h2值位置上存储的样本
    • Query与上述样本计算精确的相似度,并排序
    • 按照顺序返回结果。

    E2LSH方法存在两方面的不足[8]:首先是典型的基于概率模型生成索引编码的结果并不稳定。虽然编码位数增加,但是查询准确率的提高确十分缓慢;其次是需要大量的存储空间,不适合于大规模数据的索引。E2LSH方法的目标是保证查询结果的准确率和查全率,并不关注索引结构需要的存储空间的大小。E2LSH使用多个索引空间以及多次哈希表查询,生成的索引文件的大小是原始数据大小的数十倍甚至数百倍。

    Hashcode of p-stable distribution

    E2LSH可以说是分层法基于p-stable distribution的应用。另一种当然是转换成hashcode,则定义哈希函数如下:

    h2

    其中,a和v都是d维向量,a由正态分布产生。同上,选择k个上述的哈希函数,得到一个k位的hamming码,按照”哈希技术分类”中描述的技术即可使用该算法。

    Reference

    [1]. Ai L, Yu J, He Y, et al. High-dimensional indexing technologies for large scale content-based image retrieval: a review[J]. Journal of Zhejiang University SCIENCE C, 2013, 14(7): 505-520.

    [2]. Datar M, Immorlica N, Indyk P, et al. Locality-sensitive hashing scheme based on p-stable distributions[C]//Proceedings of the twentieth annual symposium on Computational geometry. ACM, 2004: 253-262.

    [3]. Kulis B, Grauman K. Kernelized locality-sensitive hashing[J]. Pattern Analysis and Machine Intelligence, IEEE Transactions on, 2012, 34(6): 1092-1104.

    [4]. Salakhutdinov R, Hinton G. Semantic hashing[J]. International Journal of Approximate Reasoning, 2009, 50(7): 969-978.

    [5]. Liu W, Wang J, Ji R, et al. Supervised hashing with kernels[C]//Computer Vision and Pattern Recognition (CVPR), 2012 IEEE Conference on. IEEE, 2012: 2074-2081.

    [6]. Gionis A, Indyk P, Motwani R. Similarity search in high dimensions via hashing[C]//VLDB. 1999, 99: 518-529.

    [7]. http://web.mit.edu/andoni/www/LSH/

    [8]. http://blog.csdn.net/jasonding1354/article/details/38237353

    文章出处:http://blog.csdn.net/stdcoutzyx/article/details/44456679



    位置敏感哈希(Locality Sensitive Hashing,LSH)是近似最近邻搜索算法中最流行的一种,它有坚实的理论依据并且在高维数据空间中表现优异。由于网络上相关知识的介绍比较单一,现就LSH的相关算法和技术做一介绍总结,希望能给感兴趣的朋友提供便利,也希望有兴趣的同道中人多交流、多指正。


    1、LSH原理

    最近邻问题(nearest neighbor problem)可以定义如下:给定n个对象的集合并建立一个数据结构,当给定任意的要查询对象时,该数据结构返回针对查询对象的最相似的数据集对象。LSH的基本思想是利用多个哈希函数把高维空间中的向量映射到低维空间,利用低维空间的编码来表示高维向量。通过对向量对象进行多次哈希映射,高维向量按照其分布以及自身的特性落入不同哈希表的不同桶中。在理想情况下可以认为在高维空间中位置比较接近的向量对象有很大的概率最终落入同一个桶中,而距离比较远的对象则以很大的概率落入不同的桶中。因此在查询的时候,通过对查询向量进行同样的多次哈希操作,综合多个哈希表中的查询操作得到最终的结果。


    图1 LSH哈希桶演示

    使用哈希函数对整个数据集进行过滤,得到可能满足查询条件的点再计算距离,这样就避免了查询点与数据集中所有点进行距离计算,提高了查询效率。该框架可以被称为过滤-验证框架。

    2、LSH函数族定义

    为了形式化地描述LSH使用的哈希函数的性质,现定义LSH函数族概念。

    令S为d维数据点的数据域,D为相似性度量函数,p和q为S中任意两点。函数族H={h:S->U}被称为(r1,r2,p1,p2)-敏感的,当且仅当:

    通过使用LSH函数族中函数进行哈希,可以保证距离近的点冲突的概率大于距离远的点冲突的概率。

    3、通用的LSH算法框架

    (1)构建LSH索引(哈希过程,Hashing)

    定义一个函数族G={g:S->U},其中g(v)=(h1(v),...,hk(v)),hi∈H,独立随机地从G中选择L个哈希函数g1,...,gL。对于数据集中任意一点v,将其存储到桶gi(v)中,i=1,...,L。

    这种算法是完全索引算法(full-indexing algorithms),它为每个可能的查询点提供一个查询表,因此,响应一个查询点,该算法只需在特殊构造的哈希表中进行一次查询(look-up)。

    (2)LSH搜索算法

    对于一个查询点q以及给定的距离阈值r,搜索桶g1(q),...,gL(q),取出其中的所有点v1,...,vn作为候选近似最近邻点。对于任意的vj,如果D(q,vj)<=r,那么返回vj,其中D为相似性度量函数。

    在创建LSH索引时,选取的哈希函数是k个LSH函数的串联函数,这样就相对拉大了距离近的点冲突的概率pn与距离远的点冲突的概率pf之间的差值,但这同时也使这两个值一起减小了,于是需要同时使用L张哈希表来加大pn同时减小pf。通过这样的构造过程,在查询时,与查询点q距离近的点就有很大的概率被取出作为候选近似最近邻点并进行最后的距离计算,而与查询点q距离远的点被当作候选近似最近邻点的概率则很小,从而能够在很短的时间内完成查询。


    图2 通用LSH策略示意图


    转载请注明作者及文章出处:http://blog.csdn.net/jasonding1354/article/details/38227085


    参考资料:

    1、陈永健.基于内容的大规模图像检索关键技术研究[D].华中科技大学.2011

    2、凌康.基于位置敏感哈希的相似性搜索技术研究[D].南京大学.2012


    上一节,我们分析了LSH算法的通用框架,主要是建立索引结构和查询近似最近邻。这一小节,我们从p稳定分布LSH(p-Stable LSH)入手,逐渐深入学习LSH的精髓,进而灵活应用到解决大规模数据的检索问题上。

    对应海明距离的LSH称为位采样算法(bit sampling),该算法是比较得到的哈希值的海明距离,但是一般距离都是用欧式距离进行度量的,将欧式距离映射到海明空间再比较其的海明距离比较麻烦。于是,研究者提出了基于p-稳定分布的位置敏感哈希算法,可以直接处理欧式距离,并解决(R,c)-近邻问题。

    1、p-Stable分布

    定义:对于一个实数集R上的分布D,如果存在P>=0,对任何n个实数v1,…,vn和n个满足D分布的变量X1,…,Xn,随机变量ΣiviXi和(Σi|vi|p)1/pX有相同的分布,其中X是服从D分布的一个随机变量,则称D为 一个p稳定分布。

    对任何p∈(0,2]存在稳定分布:

    p=1是柯西分布,概率密度函数为c(x)=1/[π(1+x2)];

    p=2时是高斯分布,概率密度函数为g(x)=1/(2π)1/2*e-x^2/2

    利用p-stable分布可以有效的近似高维特征向量,并在保证度量距离的同时,对高维特征向量进行降维,其关键思想是,产生一个d维的随机向量a,随机向量a中的每一维随机的、独立的从p-stable分布中产生。对于一个d维的特征向量v,如定义,随机变量a·v具有和i|vi|p)1/pX一样的分布,因此可以用a·v表示向量v来估算||v||

    2、p-Stable分布LSH中的哈希函数

    p-Stable分布的LSH利用p-Stable的思想,使用它对每一个特征向量v赋予一个哈希值。该哈希函数是局部敏感的,因此如果v1和v2距离很近,它们的哈希值将相同,并被哈希到同一个桶中的概率会很大。

    根据p-Stable分布,两个向量v1和v2的映射距离a·v1-a·v2和||v1-v2||p的分布是一样的。

    a·v将特征向量v映射到实数集R,如果将实轴以宽度w等分,并对每一段进行标号,则a·v落到那个区间,就将此区间标号作为哈希值赋给它,这种方法构造的哈希函数对于两个向量之间的距离具有局部保护作用。

    哈希函数格式定义如下:

    ha,b(v):Rd->N,映射一个d维特征向量v到一个整数集。哈希函数中又两个随机变量a和b,其中a为一个d维向量,每一维是一个独立选自满足p-Stable的随机变量,b为[0,w]范围内的随机数,对于一个固定的a,b,则哈希函数ha,b(v)为



    图1 p-Stable LSH在二维空间的示例

    3、特征向量碰撞概率

    随机选取一个哈希函数ha,b(v),则特征向量v1和v2落在同一桶中的概率该如何计算呢?

    首先定义c=||v1-v2||p,fp(t)为p-Stable分布的概率密度函数的绝对值,那么特征向量v1和v2映射到一个随机向量a上的距离是|v1-a·v2|<w,即|(v1-v2)·a|<w,根据p-Stable分布的特性,||v1-v2||pX=|cX|<w,其中随机变量X满足p-Stable分布。

    可得其碰撞概率p(c):

     

    根据该式,可以得出两个特征向量的冲突碰撞概率随着距离c的增加而减小。

    4、p-Stable分布LSH的相似性搜索算法

    经过哈希函数哈希之后,g(v)=(h1(v),...,hk(v)),但将(h1(v),...,hk(v))直接存入哈希表,即占用内存,又不便于查找,为解决此问题,现定义另外两个哈希函数:


    由于每一个哈希桶(Hash Buckets)gi被映射成Zk
    ,函数h1是普通哈希策略的哈希函数,函数h2用来确定链表中的哈希桶。

    (1)要在一个链表中存储一个哈希桶gi(v)=(x1,...,xk)时,实际上存的仅仅是h2(x1,...,xk)构造的指纹,而不是存储向量(x1,...,xk),因此一个哈希桶gi(v)=(x1,...,xk)在链表中的相关信息仅有标识(identifier)指纹h2(x1,...,xk)和桶中的原始数据点。

    (2)利用哈希函数h2,而不是存储gi(v)=(x1,...,xk)的值有两个原因:首先,用h2(x1,...,xk)构造的指纹可以大大减少哈希桶的存储空间;其次,利用指纹值可以更快的检索哈希表中哈希桶。通过选取一个足够大的值以很大的概率来保证任意在一个链表的两个不同的哈希桶有不同的h2指纹值。


    图2 桶哈希策略示意图

    5、不足与缺陷

    LSH方法存在两方面的不足:首先是典型的基于概率模型生成索引编码的结果并不稳定。虽然编码位数增加,但是查询准确率的提高确十分缓慢;其次是需要大量的存储空间,不适合于大规模数据的索引。E2LSH方法的目标是保证查询结果的准确率和查全率,并不关注索引结构需要的存储空间的大小。E2LSH使用多个索引空间以及多次哈希表查询,生成的索引文件的大小是原始数据大小的数十倍甚至数百倍。


    转载请注明作者及文章出处:http://blog.csdn.net/jasonding1354/article/details/38237353


    参考资料:

    1、王旭乐.基于内容的图像检索系统中高维索引技术的研究[D].华中科技大学.2008

    2、M.Datar,N.Immorlica,P.Indyk,and V.Mirrokni,“Locality-SensitiveHashing Scheme Based on p-Stable Distributions,”Proc.Symp. ComputationalGeometry, 2004.

    3、A.Andoni,“Nearest Neighbor Search:The Old, theNew, and the Impossible”PhD dissertation,MIT,2009.

    4、A.Andoni,P.Indyk.E2lsh:Exact Euclidean locality-sensitive hashing.http://web.mit.edu/andoni/www/LSH/.2004.



    搜集了快一个月的资料,虽然不完全懂,但还是先慢慢写着吧,说不定就有思路了呢。

      开源的最大好处是会让作者对脏乱臭的代码有羞耻感。

      当一个做推荐系统的部门开始重视【数据清理,数据标柱,效果评测,数据统计,数据分析】这些所谓的脏活累活,这样的推荐系统才会有救。

      求教GitHub的使用。

      简单不等于傻逼。

      我为什么说累:我又是一个习惯在聊天中思考前因后果的人,所以整个大脑高负荷运转。不过这样真不好,学习学成傻逼了。

      研一的最大收获是让我明白原来以前仰慕的各种国家自然基金项目,原来都是可以浑水摸鱼忽悠过去的,效率不高不说,还有可能有很多错误,哎,我就不说了。

    一、问题来源

      查找LSH发现的,这个是谷歌现在的网页去重方案。但是simHash和LSH有什么联系呢?提前透漏下,simHash本质上是一种LSH。正因为它的局部敏感性(这段的局部敏感性指的是非常相似的文本,即便只差一个字符,md5后的序列也可能非常不同,但是simHash之后的序列可能只是某几位不同),所以我们可以使用海明距离来衡量simhash值的相似度。

      simhash是google用来处理海量文本去重的算法。google出品,你懂的。simhash最牛逼的一点就是将一个文档,最后转换成一个64位的字节,暂且称之为特征字,然后判断重复只需要判断他们的特征字的距离是不是<n(根据经验这个n一般取值为3),就可以判断两个文档是否相似。

      谷歌出品嘛,简单实用。

    二、算法解析

    2.1 算法伪代码

      1、分词,把需要判断文本分词形成这个文章的特征单词。最后形成去掉噪音词的单词序列并为每个词加上权重,我们假设权重分为5个级别(1~5)。比如:“ 美国“51区”雇员称内部有9架飞碟,曾看见灰色外星人 ” ==> 分词后为 “ 美国(4) 51区(5) 雇员(3) 称(1) 内部(2) 有(1) 9架(3) 飞碟(5) 曾(1) 看见(3) 灰色(4) 外星人(5)”,括号里是代表单词在整个句子里重要程度,数字越大越重要。

      2、hash,通过hash算法把每个词变成hash值,比如“美国”通过hash算法计算为 100101,“51区”通过hash算法计算为 101011。这样我们的字符串就变成了一串串数字,还记得文章开头说过的吗,要把文章变为数字计算才能提高相似度计算性能,现在是降维过程进行时。

      3、加权,通过 2步骤的hash生成结果,需要按照单词的权重形成加权数字串,比如“美国”的hash值为“100101”,通过加权计算为“4 -4 -4 4 -4 4”;“51区”的hash值为“101011”,通过加权计算为 “ 5 -5 5 -5 5 5”。

      4、合并,把上面各个单词算出来的序列值累加,变成只有一个序列串。比如 “美国”的 “4 -4 -4 4 -4 4”,“51区”的 “ 5 -5 5 -5 5 5”, 把每一位进行累加, “4+5 -4+-5 -4+5 4+-5 -4+5 4+5” ==》 “9 -9 1 -1 1 9”。这里作为示例只算了两个单词的,真实计算需要把所有单词的序列串累加。

      5、降维,把4步算出来的 “9 -9 1 -1 1 9” 变成 0 1 串,形成我们最终的simhash签名。 如果每一位大于0 记为 1,小于0 记为 0。最后算出结果为:“1 0 1 0 1 1”。

    2.2 simHash和传统哈希的区别

      大家可能会有疑问,经过这么多步骤搞这么麻烦,不就是为了得到个 0 1 字符串吗?我直接把这个文本作为字符串输入,用hash函数生成 0 1 值更简单。其实不是这样的,传统hash函数解决的是生成唯一值,比如 md5、hashmap等。md5是用于生成唯一签名串,只要稍微多加一个字符md5的两个数字看起来相差甚远;hashmap也是用于键值对查找,便于快速插入和查找的数据结构。不过我们主要解决的是文本相似度计算,要比较的是两个文章是否相识,当然我们降维生成了hashcode也是用于这个目的。看到这里估计大家就明白了,我们使用的simhash就算把文章中的字符串变成 01 串也还是可以用于计算相似度的,而传统的hashcode却不行。我们可以来做个测试,两个相差只有一个字符的文本串,“你妈妈喊你回家吃饭哦,回家罗回家罗” 和 “你妈妈叫你回家吃饭啦,回家罗回家罗”。

      通过simhash计算结果为:

      1000010010101101111111100000101011010001001111100001001011001011

      1000010010101101011111100000101011010001001111100001101010001011

      通过 hashcode计算为:

      1111111111111111111111111111111110001000001100110100111011011110

      1010010001111111110010110011101

      大家可以看得出来,相似的文本只有部分 01 串变化了,而普通的hashcode却不能做到,这个就是局部敏感哈希的魅力。目前Broder提出的shingling算法和Charikar的simhash算法应该算是业界公认比较好的算法。

      在simhash的发明人Charikar的论文中并没有给出具体的simhash算法和证明,“量子图灵”得出的证明simhash是由随机超平面hash算法演变而来的。

      现在通过这样的转换,我们把库里的文本都转换为simhash 代码,并转换为long类型存储,空间大大减少。现在我们虽然解决了空间,但是如何计算两个simhash的相似度呢?难道是比较两simhash的01有多少个不同吗?对的,其实也就是这样,我们通过海明距离(Hamming distance)就可以计算出两个simhash到底相似不相似。两个simhash对应二进制(01串)取值不同的数量称为这两个simhash的海明距离。举例如下: 10101 和 00110 从第一位开始依次有第一位、第四、第五位不同,则海明距离为3。对于二进制字符串的a和b,海明距离为等于在a XOR b运算结果中1的个数(普遍算法)。

      simhash和普通hash最大的不同在于传统的hash函数虽然也可以用于映射来比较文本的重复,但是对于可能差距只有一个字节的文档也会映射成两个完全不同的哈希结果,而simhash对相似的文本的哈希映射结果也相似。

      http://www.lanceyan.com/tech/arch/simhash_hamming_distance_similarity.html

      http://blog.sina.com.cn/s/blog_81e6c30b0101cpvu.html

      权重该如何指派呢?我只知道用TF-IDF算法。

    三、算法实现

      谁有容易理解的java或者matlab代码,可以发短消息给我,一起为大家服务。 

    四、对比其他去重算法

    4.1 百度

      百度的去重算法最简单,就是直接找出此文章的最长的n句话,做一遍hash签名。n一般取3。 工程实现巨简单,据说准确率和召回率都能到达80%以上。

      百度的去重算法没有这么傻瓜吧?据一个百度凤巢出来的同事是这么说的。而且我个人觉得简单不等于傻逼。

    4.2 shingle算法

      shingle原理略复杂,不细说。 shingle算法我认为过于学院派,对于工程实现不够友好,速度太慢,基本上无法处理海量数据。

    五、问题扩展

      问题:一个80亿的64-bit指纹组成的集合Q,对于一个给定64-bit的指纹F,如何在a few millionseconds中找到Q中和f至多只有k(k=3)位差别的指纹。
      看文献吧。

      我想的是能否借鉴AC自动机一类的算法,来做匹配,只不过匹配规则是海明距离小于3。我说的是优化后的精确匹配了。

      http://grunt1223.iteye.com/blog/964564

      http://blog.csdn.net/lgnlgn/article/details/6008498

      http://blog.sina.com.cn/s/blog_81e6c30b0101cpvu.html

    六、意外收获

      1.python的计算能力确实很强,float可以表示任意长度的数字,而对应java、c++只能用其他办法来实现了,比如java的BigIneteger,对应的位操作也只能利用类方法。。。汗。。。
    另外说明,位运算只适合整数哦。。。因为浮点的存储方案决定不能位运算,如果非要位运算,就需要Float.floatToIntBits,运算完,再通过Float.intBitsToFloat转化回去。(java默认的float,double的hashcode其实就是对应的floatToIntBits的int值)。

      2.百度竞价排名系统:凤巢系统

      3.大神关于就业读研的感触:http://yanyiwu.com/life/2014/10/11/choices-change-my-life.html

    七、编者注

      参考文献是混合交叉的,也就是说,在第1中的参考文献也可能在第2中引用了,但是第2中未作标注。为什么这么些呢?若是以前把所有的参考文献直接放在最后,这样很不方便日后的查找,不过博客园又不想word那样引用方便,所以就取巧了。

      以后的博文,未作生命的也按词处理。



    LSH local sensitive hash,来自于 mining of massive datasets

    包括lsh的详细介绍以及针对不同距离函数的LSH。

    作用:
    解决的问题:相似性计算,避免两两计算,提供一组Hash函数,将相似的pair放在一个bucket里面,降低计算规模。
    约束:
    Hash函数的要求:
    1.相似的pair比不相似的paire更容易成为candidate
    2.识别candidate paire的效率要比从所有pair中识别candidate pair效率高(利用minhash)
    3.combinable 技术可以更好的降低false positive/negative
    4.combinable 技术识别candidate pair时间更少
    Local sensitive hash function: 是一组hash函数F, 如果f(x) = f(y),说明x,y是candiadte pair。 如果f(x) != f(y),x,y不是candidate pair。
    LSH函数集合将原始的特征规模降低为|F|,也就是Hash函数的个数。
    LSH需要符合如下约束,d是距离度量函数,d1 < d2, p1 > p2:

    if d(x,y) <= d1, p(f(x) = f(y)) >= p1
    if d(x,y) >= d2, p(fx) = f(y)) <= p2 

    则称为(d1,d2,p1,p2)-sensitive
    这两个约束说明两个问题:
    1.如果x,y的距离小于d1, x,y成为candidate pair的概率要最小为 p1,尽量保证距离小的以大概率成为pair。
    2.如果x,y的距离大于d2,x,y成为candidate pair概率最大伪p2, 保证距离大的以极小的概率成为pair。
    这就要求,随着距离正大,成为pair的概率要降低,符合常识。
    我理解d1,d2的约束是为了概念更严格,因为有的时候d1<d2,p1 不一定大于p2(欧氏距离),加上d1,d2的约束,在dx ~[0,d1], dy~[d2,无穷]这两个集合里,dx < dy,p1>p2一定成立 

    combining tech:
    LSH提供hash function,保证candidate pair能在一起,而 combine 技术可以更好的延伸这个概念
    combine技术有两种: and-construct or-constrauct,其实也就是band tech.
    F为lsh集合, F'是针对F进行combile技术结果:
    and-construct:将F中r个hash 函数作为一组,保证fi(x)=fi(y), i=1,2...r,也就是r个hash值都相等才算相等,显然限制更加严格 (d1,d2,p1^r, p2^r)   p1^r  < p1,进一步降低candidate pair的个数
    or-construct :将F中r和hash函数作为一组,保证fi(x)=fi(y)中有一个为真则为真,i=1,2...r,限制变少(d1,d2,1-(1-p1)^r, 1-(1-p2)^r),也就是(1-p1)^r表示都不想等的概率。
    两者结合起来,1-(1-p1^r)^m,  r*m=hash函数个数
    之前的博文中也提到了类这样的技术,min-hash 和banding技术的集合:
    先利用and-construct,保证只有极其相似hash值相同概率才高,降低candidate pair的规模,然后利用 or-construct技术,保证整体上相似的pair至少在某个band里面成为candidate pair

    整体来讲,LSH 就是基于距离度量函数提供一组hash函数,满足上面提到的约束,保证越相似的pair hash值相同的概率越高,能够成为candidate pair,同一hash值里面的元素少,降低整体的计算规模,同时利用and/or-construct,一方面降低计算规模,另一方面保证lsh的整体召回率,也就是相似pair至少会在某个band里面成为candidate pair。

    LSH for different distance measure:
    目前的问题是针对不同的距离度量函数,提供不同local sensitive hash函数,符合上面的条件
    jaccard的距离的LSH之前已经说过不再具体介绍,min-hash
    2.哈明距离
    计算x,y里面不同bit的个数。
    这个也很简单,hash函数集合F中,fi(x) = xi即可。
    其实这个和simhash的后续处理一致
    3.cosin 相似性
    jaccard/哈名距离 主要是基于特征字面值进行处理,相等或者不相等。而cosin计算的是夹角,而非计算两个向量里相同元素的个数。
    比如[1,2,3,4,5][10,20,30,40,50]的cosin值为1,夹角为0。
    假定d(x,y)表示向量x,y的相似性,对应cos中的夹角theta.
    LSH函数这样定义:假定x,y的特征维数为N,random的选择K个N维度向量V={v1,v2...vk}
    定义 d(v1,x)表示v1,x的夹角,基于V,定义LSH集合 F={f1,f2...fk},其中 fi(x)=sign, sign= {-1,+1},如果x与vi的夹角>90,sign=-1; 如果x与vi的夹角<=90,则sign = -1;
    基于F的定义,
    d(x,y)=0,表示两个x,y相等,则无论V取值如何fi(x) =fi(y)的概率p = 1.
    d(x,y)=pi/2,表示x,y夹角为90度,则fi(x)=fi(y)的概率为1-pi/(2*pi) = 1-0.5=0.5
    d(x,y)=pi,表示x,y的夹角为180,则fi(x)=fi(y)的概率为0
    上面是三个比较特殊的夹角,针对normal的d(x,y),则有:
    fi(x)=fi(y)的概率p1= 1-d(x,y)/pi,符合LSH的约束。
    (d1,d2,1-d1/pi, 1-d2/pi)-sensitive

    每个特征点,经过LSH处理,生成K维的{-1,+1}的向量,利用and-construct or-construct进一步优化即可
    这里需要考虑的是如何选择K特征向量V,论文提高考虑要服从高斯分布。

    4.欧式距离
    欧式距离,L2-norm,计算两个点在欧式空间的距离。这个同cosin相似性一样,不能通过字面的相等不相等来计算。
    比如[1,1,1]、[2,2,2] 的距离小于[1,1,1]、[10,10,10]的距离。
    假定d(x,y)表示向量x,y的距离,值越大,相似性越低。
    LSH的定义为:选择一条直线,水平或者垂直方向(针对多维数据,则取相应的直线),对直线按照宽度为a等分,利用用户在这个维度上的值,计算应该落在那一块,针对LSH 集合F,
    fi(x) = (xi, a)~xi/a
    基于F的定义,我们将情况分成2个部分:
    1,x,y与直线平行:
         d(x,y)为x,y的距离,d(x,y)< a,fi(x)=fi(y)的概率至少为p=(a-d(x,y))/a = 1 - d(x,y)/a:
         d=0, 则p = 1
         d = a/2,则p=0.5
         p= 0.1a, 则 p = 0.9
         p = a, 则p = 0
    2.x,y与直线有夹角theta
         如果d > a时,是有可能落在同一bucket中,比如下图的y,m。
         
         根据cos法则,落在水平直线上的距离为d*cos(theta),如果距离刚好是a,可以计算出theta,则落在一个bucket的概率最多为1-theta/90,如果d*cos(theta)<a,则theta变大,概率变低。随着d的变大,概率降低
         如果d=2a,则theta=60,p=1/3
         如果d=sqrt(a),则theta=45,p=1/2
        
     则为(a/2, 2a, 1/2,1/3)-sensitive,符合d1>d2, p2< p1的约束。
    解释一下,如果距离小于a/2,至少以p=1/2的概率落在一起,如果d变小,落在一个bucket的概率曾江;如果d>2a,则最多1/3的概率落在一起,如果d变大,摞在一起的概率一定降低    
     这说明一个事情,d1<d2,则p1>p2的成立条件是[0,d1][d2,~],大多数情况下(jaccard,hamming,cos),如果d1<d2,则p1>p2对任何d1<d2关系都成立。但是在欧式距离不一定。这是因为LSH F集合导致的。

    不过在实际使用中,我们定义LSH 集合F,F = {f1,f2....fk},fi(x)为x的第i维在对应直线上的bucke id,具体a的大小 依赖于业务,如果d一定,那么越大,落在一起的概率就越高,无论d1还是d2

    如果d(x,y) < d~a/2,则fi(x)=fi(y)的概率p=(a-d)/a = 0.5
    |
    |                                                                           
    |                                                                  m.       z.
    |
    |
    |                                                            x. y.
    |
    |
    |
    |
    |
    |
    |--------------|--------------|--------------|--------------|--------------|--------------|--------------|


    两点之间的距离可以用两种方式来衡量,一是几何距离,二是非几何距离。很显然距离的定义满足下面的条件:

    • d(x,y) > 0.
    • d(x,y) = 0 iff x = y.
    • d(x,y) = d(y,x).
    • d(x,y) < d(x,z) + d(z,y)

    几何距离包括:

    • L2 norm : d(x,y) 是平方和的开方
    • L1 norm : d(x,y) 是每个维度的距离之和
    • L∞ norm : d(x,y) 是x和y在每个维度上距离的最大值

    非几何距离用的就比较多了:

    • Jaccard距离:1减去Jaccad相似度
    • 余弦距离:两个向量之间的角度
    • 编辑距离(Edit distance):将一个串变为另一个串需要的插入或删除次数
    • 海明距离(Hamming Distance):Bit向量中不同位置的个数

    这里有一个重要的公理:三角形公理(Triangle Inequality),也就是距离的第四个性质。编辑距离d(x,y) = |x| + |y| – 2|LCS(x,y)|,其中LCS是longest common subsequence,最长公共子序列。

    LSH的一个核心思想就是两个元素哈希值相等的概率等于两个元素之间的相似度。

    下面介绍一个重要概念:Hash Family,哈希家族?不管怎么翻译,它指的是能够判断两个元素是否相等(h(x) = h(y) )的Hash函数集合。LS Hash Family,局部敏感哈希家族的定义是满足下面两个条件的哈希函数家族:

    • 如果d(x,y) < d1,那么哈希家族H中的哈希函数h满足h(x) = h(y)的概率至少是p1.
    • 如果d(x,y) > d2,那么哈希家族H中的哈希函数h满足h(x) = h(y)的概率至多是p2.

    就是如果x和y离得越近,Pr[h(p)=h(q)]就越大。如果x和y离得越远,Pr[h(p)=h(q)]就越小。我们把局部敏感哈希家族记为(d1,d2,p1,p2)-sensitive。那什么样的函数满足呢?Jaccard就是。我们令S为一个集合,d是Jaccard距离,有Prob[h(x)=h(y)] = 1-d(x,y),我们就可以得到一个局部敏感哈希家族:a(1/3, 2/3, 2/3, 1/3)-sensitive。事实上,只要满足d1<d2,就可以得到一个局部敏感的哈希家族:(d1,d2,(1-d1),(1-d2))-sensitive。

    (d1,d2,p1,p2)-sensitive将整个概率空间分成了三部分:<p1,p1-p2,>p2。为了有更好的区分度,我们想让p1-p2的空间尽可能小,让d2-d1尽可能大。选择合适的参数,能够有类似于下面的S曲线应该就是不错的了。可如何来做呢?

    image

    定义两种哈希函数的操作:AND和OR。

    AND操作:在局部敏感哈希家族H中选出r个哈希哈数,构成哈希家族H’。对于H’家族中的h = [h1,…,hr],h(x)=h(y)当且仅当对所有的i,所有hi(x)=hi(y)都满足。这样得到的H’同样也是一个局部敏感哈希家族。并且若源哈希家族是(d1,d2,p1,p2)-sensitive,新哈希家族H’是(d1,d2,(p1)^r,(p2)^r)-sensitive。

    OR操作:在局部敏感哈希家族H中选出b个哈希哈数,构成哈希家族H’。对于H’家族中的h = [h1,…,hb],h(x)=h(y)当且仅当存在i,满足hi(x)=hi(y)。这样得到的H’同样也是一个局部敏感哈希家族。并且若源哈希家族是(d1,d2,p1,p2)-sensitive,新哈希家族H’是(d1,d2,1-(1-p1)^b,1-(1-p2)^b)-sensitive。

    可以看出AND操作是降低了概率,但如果选取一个合适的r,可以使下限概率接近0,而上限概率没有多大影响。类似的,OR操作是增加了概率,但如果选择一个合适的d,可以使上限概率接近1,而下限概率没有多大影响。

    我们对AND操作和OR操作做级联:

    AND-OR,1-(1-p^r)^b

    OR-AND,(1-(1-p)^b)^r

    举个例子,1-(1-p^4)^4,当p取不同值时:

    p 1-(1-p4)4
    .2 .0064
    .3 .0320
    .4 .0985
    .5 .2275
    .6 .4260
    .7 .6666
    .8 .8785
    .9 .9860

    (1-(1-p)^4)^4,当p取不同值时:

    p
    (1-(1-p)4)4
    .1
    .0140
    .2
    .1215
    .3
    .3334
    .4
    .5740
    .5
    .7725
    .6
    .9015
    .7
    .9680
    .8
    .9936

    得到这样的S曲线之后,可以找到一个点t,满足1-(1-t^r)^b = t。在t点之后,概率快速上升,在t点之前,概率快速下降。根据需要的灵敏度,可以选择合适的上限概率和下限概率来满足应用需求。

    使用linear search进行二次筛选

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

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

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

    来看一下LSH的复杂度:

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

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

    This entry was posted in  ComputingTheories and tagged  Big DataLSH by  Jason KIM. Bookmark the permalink.

    Related Posts



    二.simHash算法简介

      以前写的一个介绍simHash的。

      1、分词,把需要判断文本分词形成这个文章的特征单词。最后形成去掉噪音词的单词序列并为每个词加上权重,我们假设权重分为5个级别(1~5)。比如:“ 美国“51区”雇员称内部有9架飞碟,曾看见灰色外星人 ” ==> 分词后为 “ 美国(4) 51区(5) 雇员(3) 称(1) 内部(2) 有(1) 9架(3) 飞碟(5) 曾(1) 看见(3) 灰色(4) 外星人(5)”,括号里是代表单词在整个句子里重要程度,数字越大越重要。

      2、hash,通过hash算法把每个词变成hash值,比如“美国”通过hash算法计算为 100101,“51区”通过hash算法计算为 101011。这样我们的字符串就变成了一串串数字,还记得文章开头说过的吗,要把文章变为数字计算才能提高相似度计算性能,现在是降维过程进行时。

      3、加权,通过 2步骤的hash生成结果,需要按照单词的权重形成加权数字串,比如“美国”的hash值为“100101”,通过加权计算为“4 -4 -4 4 -4 4”;“51区”的hash值为“101011”,通过加权计算为 “ 5 -5 5 -5 5 5”。

      4、合并,把上面各个单词算出来的序列值累加,变成只有一个序列串。比如 “美国”的 “4 -4 -4 4 -4 4”,“51区”的 “ 5 -5 5 -5 5 5”, 把每一位进行累加, “4+5 -4+-5 -4+5 4+-5 -4+5 4+5” ==》 “9 -9 1 -1 1 9”。这里作为示例只算了两个单词的,真实计算需要把所有单词的序列串累加。

      5、降维,把4步算出来的 “9 -9 1 -1 1 9” 变成 0 1 串,形成我们最终的simhash签名。 如果每一位大于0 记为 1,小于0 记为 0。最后算出结果为:“1 0 1 0 1 1”。

    三.算法几何意义及原理

    3.1 几何意义

      这个算法的几何意义非常明了。它首先将每一个特征映射为f维空间的一个向量,这个映射规则具体是怎样并不重要,只要对很多不同的特征来说,它们对所对应的向量是均匀随机分布的,并且对相同的特征来说对应的向量是唯一的就行。比如一个特征的4位hash签名的二进制表示为1010,那么这个特征对应的 4维向量就是(1, -1, 1, -1)T,即hash签名的某一位为1,映射到的向量的对应位就为1,否则为-1。然后,将一个文档中所包含的各个特征对应的向量加权求和,加权的系数等于该特征的权重。得到的和向量即表征了这个文档,我们可以用向量之间的夹角来衡量对应文档之间的相似度。最后,为了得到一个f位的签名,需要进一步将其压缩,如果和向量的某一维大于0,则最终签名的对应位为1,否则为0。这样的压缩相当于只留下了和向量所在的象限这个信息,而64位的签名可以表示多达264个象限,因此只保存所在象限的信息也足够表征一个文档了。

    3.2 算法原理描述性证明

      明确了算法了几何意义,使这个算法直观上看来是合理的。但是,为何最终得到的签名相近的程度,可以衡量原始文档的相似程度呢?这需要一个清晰的思路和证明。在simhash的发明人Charikar的论文中并没有给出具体的simhash算法和证明,以下列出我自己得出的证明思路。
      Simhash是由随机超平面hash算法演变而来的,随机超平面hash算法非常简单,对于一个n维向量v,要得到一个f位的签名(f<<n),算法如下:
      1,随机产生f个n维的向量r1,…rf;
      2,对每一个向量ri,如果v与ri的点积大于0,则最终签名的第i位为1,否则为0.
      这个算法相当于随机产生了f个n维超平面,每个超平面将向量v所在的空间一分为二,v在这个超平面上方则得到一个1,否则得到一个0,然后将得到的 f个0或1组合起来成为一个f维的签名。如果两个向量u, v的夹角为θ,则一个随机超平面将它们分开的概率为θ/π,因此u, v的签名的对应位不同的概率等于θ/π。所以,我们可以用两个向量的签名的不同的对应位的数量,即汉明距离,来衡量这两个向量的差异程度。
      Simhash算法与随机超平面hash是怎么联系起来的呢?在simhash算法中,并没有直接产生用于分割空间的随机向量,而是间接产生的:第 k个特征的hash签名的第i位拿出来,如果为0,则改为-1,如果为1则不变,作为第i个随机向量的第k维。由于hash签名是f位的,因此这样能产生 f个随机向量,对应f个随机超平面。下面举个例子:
      假设用5个特征w1,…,w5来表示所有文档,现要得到任意文档的一个3维签名。假设这5个特征对应的3维向量分别为:
      h(w1) = (1, -1, 1)T
      h(w2) = (-1, 1, 1)T
      h(w3) = (1, -1, -1)T
      h(w4) = (-1, -1, 1)T
      h(w5) = (1, 1, -1)T
      按simhash算法,要得到一个文档向量d=(w1=1, w2=2, w3=0, w4=3, w5=0) T的签名,
    先要计算向量m = 1*h(w1) + 2*h(w2) + 0*h(w3) + 3*h(w4) + 0*h(w5) = (-4, -2, 6) T,然后根据simhash算法的步骤3,得到最终的签名s=001。上面的计算步骤其实相当于,先得到3个5维的向量,第1个向量由h(w1),…,h(w5)的第1维组成:r1=(1,-1,1,-1,1) T;第2个5维向量由h(w1),…,h(w5)的第2维组成:r2=(-1,1,-1,-1,1) T;同理,第3个5维向量为:r3=(1,1,-1,1,-1) T.按随机超平面算法的步骤2,分别求向量d与r1,r2,r3的点积:

      d T r1=-4 < 0,所以s1=0;
      d T r2=-2 < 0,所以s2=0;
      d T r3=6 > 0,所以s3=1.
      故最终的签名s=001,与simhash算法产生的结果是一致的。
      从上面的计算过程可以看出,simhash算法其实与随机超平面hash算法是相同的,simhash算法得到的两个签名的汉明距离,可以用来衡量原始向量的夹角。这其实是一种降维技术,将高维的向量用较低维度的签名来表征。衡量两个内容相似度,需要计算汉明距离,这对给定签名查找相似内容的应用来说带来了一些计算上的困难;我想,是否存在更为理想的simhash算法,原始内容的差异度,可以直接由签名值的代数差来表示呢?



    请先阅读有关图的基本知识图的拉普拉斯矩阵分析以及谱聚类相关内容,谱哈希基于上述技术基础。

     

                谱哈希对图像特征向量的编码过程可看做是图分割问题,借助于对相似图的拉普拉斯矩阵特征值和特征向量的分析可对图分割问题提供一个松弛解。由谱聚类可知,相似图拉普拉斯矩阵的特征向量实际上就是原始特征降维后的向量,但其并不是0-1的二值向量,可通过对特征向量进行阈值化产生spectral hashing的二值编码(The bits in spectral hashing are calculated by thresholding a subset of eigenvectors of Laplacians of the similar graph).

    若原始特征向量空间用高斯核度量相似度 ,则令 为二值化后的特征向量矩阵即经Spectral Hashing后的二值特征向量,则在低维Hamming空间的平均Hamming距离可表示为。此外,What makes good code?

    (1) each bit has 50% chance of being 0 or 1;

    (2) the bits are independent of each other(always relaxed to uncorrelated).

     

    因此,spectral hashing的编码过程可描述为下述的优化问题(为了求解问题的方便,将二值中的0表示为-1):

                        

                        

     

    用Spectral 理论描述为:

                         

                         

    若没有二值的约束 ,则上述优化问题就简化为 是拉普拉斯矩阵个最小特征值所对应的特征向量构成的矩阵,通过简单的Thresholding可获取Binary Code。

     

    但上述的编码过程仅适用于训练集,而我们需要的是能够泛化到任意给定的out-of-example特征向量,因此引入来描述原始特征空间中数据点的概率分布,则上述的优化问题可表述为:

     

                         

                         
    当暂不考虑二值化约束时,上述优化问题的解即是eigenfunctions of weighted Laplace-Beltramician operactor  with  minimal eigenvalue. And with proper normalization, the eigenvectors of the discrete Laplacian defined by  points sampled from  coverges to eigenfunctions of  as .

     

    因此,就转化为如何利用服从分布的个离散的数据点求取 的特征方程的问题:

    是separable distribution时,即,亦即各维之间相互独立时, 的特征方程具有outer product 形式:

    即若 是特征值对应的一维空间 的特征方程,则 是特征值 对应的维空间的特征方程。特别的,针对 区间内均匀可分离的分布,一维空间的特征值和特征向量可通过下式求得:

                                    ----------function (1)

        ----------function (2)

     

    Summarize the spectral hashing alogrithm:

    Input:  data points  and the hashed bits 

    1. Finding the  principal components of the data using PCA;
    2. Calculating the  smallest single-dimension analytical eigenfunctions of   along every PCA direction. This is done by evaluating the  smallest eigenvalues for each direction using function (2), thus creating a list of  eigenvalues, and then sorting this list to find the  smallest eigenvalues; ???
    3. Thresholding the analytical eigenfunctions at zero, to obtain binary codes.

    分析:

    Step1中PCA的主要作用是align the axes for data points, 也就是使数据点各维之间相互独立,符合seperate distribution;

    Step2个人理解应该是先求取维数据点每一维 均匀分布区间,然后利用方程(2)求取每一维对应的最小的个特征值,因此总计有个特征值。然后在个特征值中选取最小的个,并记录其所对应的向量维度及其特征值序号,即 对;针对选取的各最小特征值,计算其对应的一维特征方程 。

    Step3是采用符号函数,对选取的特征方程进行二值化,产生二值码 

               由此可见,对图的次分割,每次都是选取维空间的某一维,并没有利用特征方程的outer-product的特性,paper 中的解释是二值化编码采用的是符号函数,且,因此一个bit的取值可由其它bits确定,失了去独立性。但其前提是建立在每一个bit对应的特征方程是由其它bits对应特征方程的outer-product,若bits之间不包含相同的特征方程,则还会继续保留各bits之间的独立性。因此outer-product的特征方程应该也可以利用。这仅是个人理解,具体效果还有待验证。

    训练集的作用主要是产生每维对应的分布区间,利用记录的个最小特征值对应的维度与特征值序号对 扩展至out-of-example。





    展开全文
  • java安全编码指南之:敏感类的拷贝

    万次阅读 2020-09-27 09:46:37
    一般来说class中如果包含了私有的或者敏感的数据的时候是允许被拷贝的。 如果一个class想被拷贝,我们是不是提供拷贝的方法就能保证class的安全了呢? 一起来看看吧。

    简介

    一般来说class中如果包含了私有的或者敏感的数据的时候是不允许被拷贝的。

    如果一个class不想被拷贝,我们是不是不提供拷贝的方法就能保证class的安全了呢?

    一起来看看吧。

    一个简单的SensitiveObject

    假如我们有下面的一个SensitiveObject,它的作用就是存储一个password,并且提供了一个修改password的方法:

    public class SensitiveObject1 {
        private char[] password;
    
        SensitiveObject1(String iniValue){
            this.password = iniValue.toCharArray();
        }
    
        public final String get() {
            return String.valueOf(password);
        }
    
        public final void doPasswordChange(){
            for(int i = 0; i < password.length; i++) {
                password[i]= '*' ;}
        }
    
        public final void printValue(){
            System.out.println(String.valueOf(password));
        }
    }
    

    看上去没什么问题,如果我们希望密码被返回之后就不能够被修改,应该怎么做呢?

    SensitiveObject的限制

    为了实现上面的功能,我们可以考虑引入一个是否返回的变量,如果返回过了,就不允许进行密码修改了。

    那么我们可以将上面的代码修改成这样:

    public class SensitiveObject2 {
        private char[] password;
        private boolean returned=false;
    
        SensitiveObject2(String iniValue){
            this.password = iniValue.toCharArray();
        }
    
        public final String get()
        {
            if(!returned) {
                returned=true;
                return String.valueOf(password);
            }else {
            throw new IllegalStateException("已经返回过了,无法重复返回");
            }
        }
    
        public final void doPasswordChange(){
            if(!returned) {
                for (int i = 0; i < password.length; i++) {
                    password[i] = '*';
                }
            }
        }
    }
    

    通过加入了returned标签,我们可以控doPasswordChange方法,只能在未返回之前进行密码修改。

    我们看下调用代码:

            SensitiveObject2 sensitiveObject2= new SensitiveObject2("www.flydean.com");
            sensitiveObject2.doPasswordEncrypt();
            System.out.println(sensitiveObject2.get());
    

    对SensitiveObject的攻击

    怎么对上述代码进行攻击呢?

    如果我们想在密码返回之后仍然对密码进行修改,怎么做到呢?

    如果SensitiveObject2可以拷贝,我们是不是就能够保存一份char[]和boolean的副本了呢?

    因为char[]属于引用拷贝,所以在拷贝的副本里面对char[]进行修改完全可以影响到原SensitiveObject2的内容。

    但是,虽然clone方法是定义在Object中的,如果子类没有实现Cloneable接口的话,将会抛出CloneNotSupportedException异常。

    考虑到SensitiveObject2不是一个final的类,我们可以通过继承SensitiveObject2来实现目的:

    public class MaliciousSubSensitiveObject extends SensitiveObject2 implements Cloneable{
        MaliciousSubSensitiveObject(String iniValue) {
            super(iniValue);
        }
    
        public MaliciousSubSensitiveObject clone(){
            MaliciousSubSensitiveObject s = null;
            try {
                s = (MaliciousSubSensitiveObject)super.clone();
            } catch(Exception e) {
                System.out.println("not cloneable");
            }
            return s;
        }
    
        public static void main(String[] args) {
            MaliciousSubSensitiveObject object1 = new MaliciousSubSensitiveObject("www.flydean.com");
            MaliciousSubSensitiveObject object2 = object1.clone();
            String password1= object1.get();
            System.out.println(password1);
            object2.doPasswordChange();
            object1.printValue();
        }
    }
    

    可以看到,虽然object1先返回了password,但是这个password被clone过的object2进行了修改,最终导致object1中的password值发生了变化。

    解决办法

    怎么解决呢?

    一个简单的方法就是将SensitiveObject class定义为final,这样就不能继承,从而避免了上诉问题。

    本文的例子:

    learn-java-base-9-to-20/tree/master/security

    本文已收录于 http://www.flydean.com/java-security-code-line-object-copy/

    最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

    欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

    展开全文
  • 比如PersepolisDownload Manager(PDM下载器)、PanDownload、Photon,上述这些下载工具要么针对性太强,能做到种子和直链资源兼顾下载的又速度太慢,对敏感资源的下载也不是太给力 其实还是要看迅雷的,只不过要用...
  • 怎么处理敏感信息?

    千次阅读 2019-10-20 19:33:53
    未经授权不得泄漏的信息, 都算是敏感信息 1.个人敏感信息 个人信息: 姓名、 性别、 年龄、 身份证号码、 电话号码。 健康信息: 健康记录、 服药记录、 健康状况。 教育记录: 教育经历、 学习课程、 考试分数。 ...

    未经授权不得泄漏的信息, 都算是敏感信息

    1.个人敏感信息

    个人信息: 姓名、 性别、 年龄、 身份证号码、 电话号码。
    健康信息: 健康记录、 服药记录、 健康状况。
    教育记录: 教育经历、 学习课程、 考试分数。
    消费记录: 所购货物、 购买记录、 支付记录。
    账户信息: 信用卡号、 社交账号、 支付记录。
    隐私信息: 家庭成员、 个人照片、 个人行程。

    2.商业敏感信息

    商业秘密: 设计程序、 制作工艺、 战略规划、 商业模式。
    客户信息: 客户基本信息、 消费记录、 订单信息、 商业合作和合同。
    雇员信息: 雇员基本信息、 工资报酬。
    需要注意的是, 上述只是一些常见的、 直观的敏感信息。 具体到你开发的信息系统, 到底什么样
    的信息是敏感信息, 什么样的信息不是敏感信息, 还需要进一步分析和界定。
    识别出敏感信息之后, 就要想办法保护这些信息了。 敏感信息的保护, 需要恰当的管理, 也需要适合的技术

    授权, 敏感信息谁能看?

    敏感信息指的是未经授权不得泄漏的信息。 这个概念可以拆分为三部分:

    1. 敏感信息是受保护的信息, 未经授权, 不得访问;
    2. 敏感信息是一段有效信息, 有信息处理需求, 比如产生、 传输、 存储、 读取、 更改、 废弃
      等;
    3. 敏感信息是有归属的信息, 不同的人有不同的权限。 经过授权, 合适的人可以执行相应的操
      作。是否需要授权是敏感信息和普通信息的最关键差异。 不同的人有不同的权限, 不同的操作需要
      不同的权限。

    该如何处理授权呢?

    第一件事情, 就是定义权限。 只有定义了权限, 才能知道如何分配和管理权限。

    在JDK中, 权限通过java.security.Permission接口来定义。 Permission接口定义权限的名称和操作

    比如, java.io.FilePermission把权限名定义为文件名, 把操作定义为:
    read
    write
    execute
    delete
    readlink

    其中, 权限的名称就是抽象了的敏感信息; 权限的操作就是对信息的处理。 如果把权限的名称和权限的操作结合起来, 就可以定义特定的权限了。 比如, 下面的例子就定义了对于文件目录“/home/myhome”的读操作

    permission java.io.FilePermission “/home/myhome”, “read”;

    第二件事情, 就是定义权限的主体。 也就是说, 要明确权限可以分派给谁。

    在JDK中, 权限的主体通过java.security.Principal接口来定义。 Principal接口可以用来表述个人, 组织或者虚拟的账户

    比如, com.sun.security.auth.UnixPrincipal可以用来表述Unix的用户。

    Principal com.sun.security.auth.UnixPrincipal “duke”

    第三件事情, 就是要定义权限的归属。

    也就是说, 有了权限的定义和权限主体的定义, 我们就可以分配权限了。 下面的例子, 就是把对“/home/duke”的读写操作权限, 赋予给了Unix用户duke。

    grant Principal com.sun.security.auth.UnixPrincipal “duke” {
    permission java.io.FilePermission “/home/duke”, “read, write”;
    }

    更详细的内容, 权限管理策略文件的语法以及API的调用, 请参阅有关Java的规范。

    这套解决方案能够实施下去, 还是有很多挑战的。 比如说, 敏感信息的操作处理过程, 也会造成信息的非授权泄漏

    特殊信息, 特殊处理

    现代信息系统资源, 一般都是多用户共享, 多应用共享, 跨边界合作的, 比如内存、 硬盘、 中央处理器和互联网。 而敏感信息是不能共享的, 如何在共享的资源内, 不留下敏感信息的踪迹?
    这是一个让人头疼的问题。

    比如说吧, 要使用敏感信息, 就要把敏感信息载入内存, 如果发生内存溢出
    攻击, 攻击者就可以绕过权限管理, 获取或者修改敏感信息, 甚至可以修改对敏感信息的操作。
    针对敏感信息的操作, 需要特殊的处理和特殊的技术。
    敏感信息的无意识泄露是一种比较常见的敏感信息泄露事件。 比如说, 把敏感信息泄露在抛出异常里, 应用日志里, 或者序列化对象里。
    比如说, 如果一个文件不存在, 一般的代码实现会倾向于抛出java.io.FileNotFoundException异常。 为了使异常信息更加直观, 我们常常把文件路径包含在异常的消息里, 或者记录在应用日志里

    java.io.FileNotFoundException: /home/duke/.ssh was not found

    这个异常信息有可能绕过权限管理, 传达给未授权用户。 这个信息里包含了三个重要的敏感信息:

    • 当前用户名是“duke”;
    • 当前用户没有配置SSH协议;
    • 有可能获知特定文件是否存在。

    当实现一个文件管理类时, 我们可能会习惯于面向对象的机制。 比如, 给定一个文件的路径, 代码就执行一定的读写操作。 至于该文件路径是什么, 包含什么内容, 是否有敏感信息, 都不在该类的考虑范围之内。

    实现这个类时, 我们更可能倾向于使用直观友好的异常信息, 而不会意识到这些异常信息可能携带敏感数据, 导致敏感数据通过异常信息泄露。
    这和我们一般的面向对象的编程习惯是不符合的, 这就要求我们特别小心。 从实现者的角度出发, 抛出的异常信息尽量做到不包含可能的敏感信息; 从调用者的角度出发, 截获的异常信息在传递到上层调用之前, 如果有必要, 需要做净化处理。 比如, 把上述的
    java.io.FileNotFoundException转化成更普通的java.io.IOException。

    java.io.IOException: An IOException was caught!

    下面的异常堆栈是不是可以接受呢?

    java.io.IOException: An IOException was caught!
    at com.example.myapp.MyHTTPSerer.myMethod(MyHTTPSerer.java:250)
    ...
    Caused by java.io.FileNotFoundException: /home/duke/.ssh was not found
    at com.example.myapp.MyFileStream.open(MyFileStream.java:249)
    

    这个异常堆栈的“Caused by”部分泄露了同样的敏感信息。 所以, 在做异常信息净化处理时,可能还需要避免传递捕获异常的堆栈。 特别是如果调用结果直接面向最终用户, 就应当尽量避免使用异常堆栈。 比如说, 在HTML页面中显示异常信息和异常堆栈, 就容易出问题。
    在后面的文章中, 我们还会讨论敏感信息及时归零的话题。 这也是对于高度敏感信息的一种特殊处理方式。

    展开全文
  • 技术敏感度 — 基层技术管理者必备

    千次阅读 2014-07-03 08:23:57
    然而,对于软件开发活动中的基层技术管理者(team lead、line manager等),我想指出被极为忽视的另一种重要能力 — 技术敏感度。 对于基层技术管理者来说,何为技术敏感度?技术敏感度表现为:1)工程师解释技术...
  • 局部敏感哈希算法

    万次阅读 2017-10-15 21:36:20
    私认为,文本的相似性可以分为两类:一类是... 语义相似性代表着,两个文本语义上的相似程度,比如“苹果”和“公司”的相似性,本篇做这一讨论,可参考笔者的另外一篇博客:  NLP︱句子级、词语级以及句子-词
  • 虽然说创业什么时候都...一般来说,中年人创业,找项目要抓住四个基本,找商机要做到可,有道理。 先来分享找项目要抓住的四个基本: 第一个基本:做,找项目要从自身熟悉的行业做起 年轻人创业,...
  • 私认为,文本的相似性...语义相似性代表着,两个文本语义上的相似程度,比如“苹果”和“公司”的相似性,本篇做这一讨论,可参考笔者的另外一篇博客:  NLP︱句子级、词语级以及句子-词语之间相似性(相关名称:
  • 文本局部敏感哈希-SimHash算法原理

    千次阅读 2016-09-18 22:10:03
    最近在思考大量文本判重的问题,由于文本数据量大,加之文本判重算法,如BF、KMP、最长公共子串、后缀数组、字典树、DFA等计算时空复杂度并适合数据量较大的工业应用场景。查找了相关资料,发现LSH(local ...
  • 朝戈《敏感者》

    千次阅读 2009-10-29 13:04:00
    朝戈《敏感者》 1986年,朝戈回到他求学四年的母校,这次,他是以一名教师的身份进入中央美术学院的。 20世纪90年代在不知不觉中悄然来临了。美术学院的高墙虽然挡住了市井的喧闹,但激烈的社会变革气息透过墙角的...
  • 一、局部敏感哈希LSH 二、Hamming 距离 三、Euclidean 距离 四、Jaccard 系数 五、参考资料 在很多问题中,从海量数据库中寻找到与查询数据相似的数据是一个很关键的问题。比如在图片检索领域,需要找到与查询图像...
  • 4. 数据包被转发时需采用队列协议按序转发,从而尽可能做到低延时。 5) 什么是AVB? AVB——以太网音视频桥接技术(Ethernet Audio Video Bridging)是IEEE的802.1任务组于2005开始制定的一套基于新的以太网...
  • 从码农到工程师:只要做到这6点

    千次阅读 多人点赞 2018-04-21 09:07:51
    许多程序员自称码农,因为每天事情总也做完,而这些工作也没有给自己带来职业上的提升,总在原地打转,自己的工作似乎随时可被新人替换,可有可无。于是,年轻些的考虑着转管理或者转行,年纪大些的则被所谓的40岁...
  • 对比敏感度 图像压缩 总结 混叠图像 我们可以在图像中看到。这是一张更好的图片显示图像混叠。所以你可以看到,这是一个径向正弦波(Radio sine wave),你可以看到,当你越来越近的时候,像素应该摆动得越来越...
  • 以纯文本形式存储敏感数据的所有方法都被认为是安全的,因为它们会将数据公开给设法取得数据源读取权限(要做到这一点可能比您想的还要容易)的任何人。您应该避免将未加密的数据保存在 Windows 注册表、配置文件...
  • 相关滤波器算法 速度做到极致

    万次阅读 2017-12-06 22:04:10
    将相关滤波跟踪算法的速度做到极致 YaqiLYU 5 个月前 相关滤波类方法从一开始能被我盯上,就是因为速度比较快,不管哪个CV算法,速度都是重要的指标之一,tracking问题尤甚,工业应用永远把速度排在性能之前...
  • BigDecimal为什么能做到高精度计算

    千次阅读 2019-08-31 22:12:18
    很多人都知道在Java高精度计算时需要使用BigDecimal,实际上,很多对数值精度敏感的领域,比如结算、财务,也确实都是使用BigDecimal这种高精度计算工具来实现的,在二进制计算机的世界了,在有限的存储介质上无法...
  • 今天和大家分享的主题是《区块链是如何做到交易数据防篡改的》?这个话题属于数据安全领域的问题,如果完全展开来说,涉及到的面非常广;那我们依然按照之前的原则,一次只讲一个核心点,掰开了揉烂了说;在讲解的...
  • 目录 前言 一、爬虫反爬虫运行现状 1、真实世界的爬虫比例 2、哭笑不得的决策思路 二、爬虫反爬虫技术现状 1、为python平反 2、无法绕开的误伤率 ...爬虫与反爬虫,是一个很阳光的行业。...这里说的阳...
  • 一些企业就算被恶意攻破服务器,也愿意公开或被人发现,因为对于企业而言,相当于信用值降到了最低,如果公开信息那就等于告诉别人自家的安全防护靠谱,所以如果某些公司被GP后,交点钱也不会公开或者报案,给...
  • 六万字 HTTP 必备干货学习,程序员懂网络怎么行,一篇HTTP入门收藏都可惜!网络知识入门必备,学习起来!
  • 未来迎,当下杂,过往

    千次阅读 2016-03-24 13:47:06
    罗辑思维出的《罗辑思维:成大事者纠结 》 ,书中大多数内容都听过,当故事听,很少会细细的回味。微信读书里看到了这本书,随手翻翻,发现这本书值得仔细玩味。尤其关于“纠结”这个话题,罗辑思维给出了良方,让...
  • Android中如何做到Service被关闭后又自动启动

    万次阅读 多人点赞 2011-12-05 09:43:23
    大部分时候,程序员也想把软件做成流氓软件,没办法,领导说了算。 我们在使用某些Android应用的时候,可能会发现安装了某应用以后,会有一些服务也会随之运行。而且,这些服务每次都会随着手机开机而启动。有的...
  • HiFi有哪些常见技术指标 手机HiFi一直都是一个热度减的话题,近期发布的不少手机也都在主打HiFi音质:采用ES9318 DAC+耳放二合一音频芯片的vivo X9s Plus,采用AKM HiFi芯片并配备HUAWEI histen音效的荣耀9...
  • 工作两年小结----勿忘初心负梦想

    千次阅读 多人点赞 2016-08-01 00:21:59
    前言:转眼又是一年,2016年7月3号是自己正式参加工作两年,入职一家新公司...我是先看完书,再看了2集电视剧,然后真的看下去了,因为张一山刻画的余罪跟自己心中的那个余罪落差太大。我甚至觉得夏雨来主演会更好一
  • 我是如何做到花8000元拔智齿的

    千次阅读 2015-05-05 22:37:38
    继续恍恍惚惚过了两年我发现自己的牙齿已经无法接受敏感食物,巧克力,大白兔和糖葫芦全部离我而去,直到2014年9月喝水都感到疼痛时我才意识到自己的牙摊上大事了。 无奈的治疗方案 提早2年治疗,减少8分...
  • 下面是吐槽,引用部分还提到距离,只有到纳秒级系统才对网线长短敏感好么,这种毫秒级的系统根本在乎这些。 竟然还说离交易前置3米,那只有同机柜或者相邻机柜的部分机器才能做到。我相信中信做colo的服务器...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 73,513
精华内容 29,405
关键字:

如何做到不敏感