如何在Python中将向量编码为矩阵汉明距离?

时间:2016-06-10 10:33:31

标签: python matrix information-retrieval hamming-distance

我喜欢开发一个查询系统,根据从数据中提取的二进制签名,找到与给定项目最相似的项目。因为我有运行时约​​束,所以我会探索最有效的方法。我试图使用scipy距离,但它太慢了。你知道任何其他有用的库或技巧,以更快的方式。

对于存在和示例场景,

我有一个长度为68的二进制值的查询向量,我有一个矩阵大小为3000Kx68的数据集。我喜欢通过使用汉明距离在此矩阵中找到最相似的项目给出查询。

感谢任何评论

3 个答案:

答案 0 :(得分:1)

好问题,我喜欢Alex和Piotr的答案。我的第一次天真尝试也导致解决时间大约800ms(在我的系统上)。我的第二次尝试,使用numpy的(un)packbits,导致速度提高了4倍。

import numpy as np

LENGTH = 68
K = 1024
DATASIZE = 3000 * K
DATA = np.random.randint(0, 2, (DATASIZE, LENGTH)).astype(np.bool)

def RandomVect():
    return np.random.randint(0, 2, (LENGTH)).astype(np.bool)

def HammingDist(vec1, vec2):
    return np.sum(np.logical_xor(vec1, vec2))

def SmallestHamming(vec):
    XorData = np.logical_xor(DATA, vec[np.newaxis, :])
    Lengths = np.sum(XorData, axis=1)
    return DATA[np.argmin(Lengths)]  # returns first smallest

def main():
    v1 = RandomVect()
    v2 = SmallestHamming(v1)
    print(HammingDist(v1, v2))

# oke, lets try make it faster... (using numpy.(un)packbits)

DATA2 = np.packbits(DATA, axis=1)
NBYTES = DATA2.shape[-1]

BYTE2ONES = np.zeros((256), dtype=np.uint8)
for i in range(0,256):
    BYTE2ONES[i] = np.sum(np.unpackbits(np.uint8(i)))

def RandomVect2():
    return np.packbits(RandomVect())

def HammingDist2(vec1, vec2):
    v1 = np.unpackbits(vec1)
    v2 = np.unpackbits(vec2)
    return np.sum(np.logical_xor(v1, v2))

def SmallestHamming2(vec):
    XorData = DATA2 ^ vec[np.newaxis, :]
    Lengths = np.sum(BYTE2ONES[XorData], axis=1)
    return DATA2[np.argmin(Lengths)]  # returns first smallest

def main2():
    v1 = RandomVect2()
    v2 = SmallestHamming2(v1)
    print(HammingDist2(v1, v2))

答案 1 :(得分:0)

如果速度明显快于此,我会感到惊讶:将数据放入pandas DataFrame(M),每个向量按列,将目标向量放入pandas系列({{1} }),

x

然后执行以下操作

import numpy as np
import pandas as pd

rows = 68
columns=3000 
M = pd.DataFrame(np.random.rand(rows,columns)>0.5)
x = pd.Series(np.random.rand(rows)>0.5)

编辑:实际上,我很惊讶这是一种更快的方式

%timeit M.apply(lambda y: x==y).astype(int).sum().idxmax()

1 loop, best of 3: 746 ms per loop

答案 2 :(得分:0)

使用SciPy中的cdist

from scipy.spatial.distance import cdist
Y = cdist(XA, XB, 'hamming')
  

计算归一化汉明距离,或两个不同意的n向量u和v之间的向量元素的比例。为了节省内存,矩阵X可以是boolean类型

参考:http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cdist.html