在对大批量数据进行图像处理的时候,比如说我提取SIFT特征,数据集为10W张图片,一个SIFT特征点是128维,一张图片提取出500个特征点,这样我们在处理的时候就是对5000万个128维的数据进行处理,这样处理所需要的耗时太长了,不符合实际生产的需要。我们需要用一种方法降低运算量,比如说降维。

  看了一些论文,提到的较多的方法是LSH(Locality Sensitive Hash),就是局部敏感哈希。我们利用LSH方法在5000万个特征点中筛选出极少量的我们需要的特征点,在对这些极少量的数据进行计算,就可以得到我们想要的结果啦。

 package com.demo.lsh;

 import com.demo.config.Constant;
import com.demo.dao.FeatureDao;
import com.demo.dao.FeatureTableDao;
import com.demo.dao.HashTableDao;
import com.demo.entity.HashTable;
import com.demo.utils.MD5Util;
import com.demo.utils.MathUtil;
import org.opencv.core.Mat;
import org.springframework.util.StringUtils; import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*; public class LSH {
//维度大小,例如对于sift特征来说就是128
private int dimention = Constant.DIMENTION;
//所需向量中元素可能的上限,譬如对于RGB来说,就是255
private int max = Constant.MAX;
//哈希表的数量,用于更大程度地削减false positive
private int hashCount = Constant.HASHCOUNT;
//LSH随机选取的采样位数,该值越小,则近似查找能力越大,但相应的false positive也越大;若该值等于size,则为由近似查找退化为精确匹配
private int bitCount = Constant.BITCOUNT;
//转化为01字符串之后的位数,等于max乘以dimensions
private int size = dimention * max;
//LSH哈希族,保存了随机采样点的INDEX
private int[][] hashFamily;
private HashTableDao hashTableDao;
/**
* 构造函数
*/
public LSH(HashTableDao hashTableDao) {
this.hashTableDao = hashTableDao;
dimention = Constant.DIMENTION;
max = Constant.MAX;
hashCount = Constant.HASHCOUNT;
bitCount = Constant.BITCOUNT;
size = dimention * max;
hashFamily = new int[hashCount][bitCount];
generataHashFamily();
} /**
* 生成随机的投影点 ,在程序第一次执行时生成。投影点可以理解为后面去数组的索引值
*/
private void generataHashFamily() {
if (new File("/home/fanxuan/data/1.txt").exists()) {
try {
InputStream in = new FileInputStream("/home/fanxuan/data/1.txt");
ObjectInputStream oin = new ObjectInputStream(in);
hashFamily = (int[][]) (oin.readObject());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}else {
Random rd = new Random();
for (int i = 0; i < hashCount; i++) {
for (int j = 0; j < bitCount; j++) {
hashFamily[i][j] = rd.nextInt(size);
}
}
try {
OutputStream out = new FileOutputStream("/home/fanxuan/data/1.txt");
ObjectOutputStream oout = new ObjectOutputStream(out);
oout.writeObject(hashFamily);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
} //将向量转化为二进制字符串,比如元素的最大范围255,则元素65就被转化为65个1以及190个0
private int[] unAray(int[] data) {
int unArayData[] = new int[size];
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i]; j++) {
unArayData[i * max + j] = 1;
}
}
return unArayData;
} /**
* 将向量映射为LSH中的key
*/
private String generateHashKey(int[] list, int hashNum) {
StringBuilder sb = new StringBuilder();
int[] tempData = unAray(list);
int[] hashedData = new int[bitCount];
//首先将向量转为二进制字符串
for (int i = 0; i < bitCount; i++) {
hashedData[i] = tempData[hashFamily[hashNum][i]];
sb.append(hashedData[i]);
}
//再用常规hash函数比如MD5对key进行压缩
MessageDigest messageDigest = null;
try{
messageDigest = MessageDigest.getInstance("MD5");
}catch (NoSuchAlgorithmException e) { }
byte[] binary = sb.toString().getBytes();
byte[] hash = messageDigest.digest(binary);
String hashV = MD5Util.bufferToHex(hash);
return hashV;
} /**
* 将Sift特征点转换为Hash存表
*/
public void generateHashMap(String id, int[] vercotr, int featureId) {
for (int j = 0; j < hashCount; j++) {
String key = generateHashKey(vercotr, j);
HashTable hashTableUpdateOrAdd = new HashTable();
HashTable hashTable = hashTableDao.findHashTableByBucketId(key);
if (hashTable != null) {
String featureIdValue = hashTable.getFeatureId() + "," + featureId;
hashTableUpdateOrAdd.setFeatureId(featureIdValue);
hashTableUpdateOrAdd.setBucketId(key);
hashTableDao.updateHashTableFeatureId(hashTableUpdateOrAdd);
} else {
hashTableUpdateOrAdd.setBucketId(key);
hashTableUpdateOrAdd.setFeatureId(String.valueOf(featureId));
hashTableDao.insertHashTable(hashTableUpdateOrAdd);
}
}
} // 查询与输入向量最接近(海明空间)的向量
public List<String> queryList(int[] data) {
List<String> result = new ArrayList<>();
for (int j = 0; j < hashCount; j++) {
String key = generateHashKey(data, j);
result.add(key);
HashTable hashTable = hashTableDao.findHashTableByBucketId(key);
if (!StringUtils.isEmpty(hashTable.getFeatureId())) {
String[] str = hashTable.getFeatureId().split(",");
for (String string : str) {
result.add(string);
}
}
}
return result;
} }

  

 package com.demo.config;

 public class Constant {
//维度大小,例如对于sift特征来说就是128
public static final int DIMENTION = 128;
//所需向量中元素可能的上限,譬如对于RGB来说,就是255
public static final int MAX = 255;
//哈希表的数量,用于更大程度地削减false positive
public static final int HASHCOUNT = 12;
//LSH随机选取的采样位数,该值越小,则近似查找能力越大,但相应的false positive也越大;若该值等于size,则为由近似查找退化为精确匹配
public static final int BITCOUNT = 32;
}

  简单的介绍下代码,构造函数LSH()用来建立LSH对象,hashTableDao为数据表操作对象,不多说;因为局部敏感哈希依赖与一套随机数,每次产生的结果都不一致,所以我们需要在程序第一次运行的时候将随机数生成并固定下来,我采用的方法是存放在本地磁盘中,也可以存放在数据库中。generateHashMap()方法为数据训练函数,int[] vercotr为特征向量,其他两个参数为我需要的标志位。queryList()方法是筛选方法。

  感谢http://grunt1223.iteye.com/blog/944894的文章。

Java实现LSH(Locality Sensitive Hash )的更多相关文章

  1. 从NLP任务中文本向量的降维问题,引出LSH(Locality Sensitive Hash 局部敏感哈希)算法及其思想的讨论

    1. 引言 - 近似近邻搜索被提出所在的时代背景和挑战 0x1:从NN(Neighbor Search)说起 ANN的前身技术是NN(Neighbor Search),简单地说,最近邻检索就是根据数据 ...

  2. Locality Sensitive Hash 局部敏感哈希

    Locality Sensitive Hash是一种常见的用于处理高维向量的索引办法.与其它基于Tree的数据结构,诸如KD-Tree.SR-Tree相比,它较好地克服了Curse of Dimens ...

  3. LSH(Locality Sensitive Hashing)原理与实现

    原文地址:https://blog.csdn.net/guoziqing506/article/details/53019049 LSH(Locality Sensitive Hashing)翻译成中 ...

  4. Locality Sensitive Hashing,LSH

    1. 基本思想 局部敏感(Locality Senstitive):即空间中距离较近的点映射后发生冲突的概率高,空间中距离较远的点映射后发生冲突的概率低. 局部敏感哈希的基本思想类似于一种空间域转换思 ...

  5. [Algorithm] 局部敏感哈希算法(Locality Sensitive Hashing)

    局部敏感哈希(Locality Sensitive Hashing,LSH)算法是我在前一段时间找工作时接触到的一种衡量文本相似度的算法.局部敏感哈希是近似最近邻搜索算法中最流行的一种,它有坚实的理论 ...

  6. 局部敏感哈希-Locality Sensitive Hashing

    局部敏感哈希 转载请注明http://blog.csdn.net/stdcoutzyx/article/details/44456679 在检索技术中,索引一直须要研究的核心技术.当下,索引技术主要分 ...

  7. 局部敏感哈希算法(Locality Sensitive Hashing)

    from:https://www.cnblogs.com/maybe2030/p/4953039.html 阅读目录 1. 基本思想 2. 局部敏感哈希LSH 3. 文档相似度计算 局部敏感哈希(Lo ...

  8. 转:locality sensitive hashing

    Motivation The task of finding nearest neighbours is very common. You can think of applications like ...

  9. 转: memcached Java客户端spymemcached的一致性Hash算法

    转自:http://colobu.com/2015/04/13/consistent-hash-algorithm-in-java-memcached-client/ memcached Java客户 ...

随机推荐

  1. 使用Compute Engine工具连接Linux VM

    Links: Connecting to Linux Instances 内容: 要连接Linux VM实例,必须要有一个SSH(Secure Shell)秘钥.无论何时连接一个LinuxVM实例(通 ...

  2. U-Boot中支持USB

    转载: http://blog.csdn.net/qiurihuanghua/article/details/6234832 今天查看了一下在P4080DS板子的U-Boot中支持USB,主要是加入U ...

  3. Shell编程基础及变量

    一.Shell脚本 1.Shell脚本的建立 由Linux命令.shell命令.程序结构控制语句和注释等内容组成. 脚本第一行 #!/bin/bash #!字符称为幻数,内核会根据它后面的解释器来确定 ...

  4. jQuery带缩略图焦点图插件

    在线演示 本地下载

  5. React Native的生命周期解析

    在React Native中使用组件来封装界面模块时,整个界面就是一个大的组件,开发过程就是不断优化和拆分界面组件.构造整个组件树的过程. 上张图涵盖了一个组件从创建.运行到销毁的整个过程.大家可以看 ...

  6. 【P1274】魔术数字游戏(搜索+剪枝+模拟)

    做完了这个题的我一口老血喷在屏幕上... 这个题难度不高(~~胡扯~~),就是爆搜就可以了,然而..判断条件灰常多,剪枝也就非常多..然而,这些判断条件又不得不必须满足,所以也就十分容易错... 说一 ...

  7. 逆向破解学习二之<TraceMe>

    这次在破解TraceMe的时候,我有看过别人的视频.但是我并没有按照别人思路走,而是完全安全自己的思路试了一次.结果破解成功.新手学破解,如果有不对的地方,还请指出来. 004013A0 crackm ...

  8. spring boot 基础学习

    构建微服务:Spring boot 入门篇 http://www.cnblogs.com/ityouknow/p/5662753.html SpringBoot入门系列:第一篇 Hello World ...

  9. JavaScript -- 操作input CheckBox 全选框

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. redis 按空间范围查询点位

    GEORADIUS GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC| ...