乘积量化Product Quantization算法 python代码实现

乘积量化Product Quantization算法 python代码实现

  • 算法简介:

乘积量化PQ(Product Quantization):

       PQ算法是图像检索中常用的一种快速搜索算法,可以大大减少计算量,具体做法如下:将D维空间切分为M个D/M维的子空间:假设现得到每张图片特征向量维度为128维,共256张图片。为了加速距离运算,现将128维向量切分成8段,如下图所示。

       分别在每一段所表示的子空间中进行K-means聚类,之后在每一段中用距离该段内距离最近的聚类中心的编号来作为索引值,即每一个128维向量被压缩为8个索引值表示的向量。保留压缩后的向量与聚类中心。

                               

                              

                                 

  • 算法实现:

        本次通过python编程实现简易的PQ算法,使用对称距离计算即直接用两压缩向量之间的海明距离进行相似性度量,并用一些简单的随机数进行了测试,之后会在实战中尝试运用。

代码段:

#作者:Puremelo
#完成时间:2018.10.13
import numpy as np
from sklearn.cluster import KMeans
class PQ:
    def __init__(self, K, L):
        self.dim = L
        self.k = K
    def cut(self, data):
        num = len(data)
        allData = []
        for i in range(num):
            Data = []
            for j in range(int(self.dim / self.k)):
                Data.append(data[i][j*int(self.dim/self.k):(j+1)*int(self.dim/self.k)])
            allData.append(Data)
        return allData
    def kmeans(self, data, K):
        estimator = KMeans(n_clusters=K)
        label = []
        centroids = []
        newdata = np.zeros([len(data), self.k])
        a = np.reshape(data, [len(data), 3, 3])
        # print(data)
        for i in range(self.k):
            fitdata = a[0][i]
            # print(fitdata)
            for w in range(1, len(data)):
                fitdata = np.row_stack((fitdata, a[w][i]))
            estimator.fit(fitdata)
            label.append(estimator.labels_)
            centroids.append(estimator.cluster_centers_)
        for j in range(self.k):
            for k in range(len(data)):
                newdata[k][j] = label[j][k]
        return label, centroids, newdata
    def compute(self, N, query, data):
        dis = np.zeros(len(data))
        for n in range(len(data)):
            for i in range(N):
                if query[i] == data[n][i]:
                    dis[n] = dis[n]
                else:
                    dis[n] = dis[n]+1
        # 按相似度从大到小返回标号
        index = dis.argsort()
        return dis, index


if __name__ == '__main__':
    data = np.random.randint(0, 3, size=(9, 9))
    pq = PQ(3, 9)
    result = pq.cut(data)
    result2, result3, newdata = pq.kmeans(result, 3)
    print(result2, result3, newdata)
    result4, index = pq.compute(3, newdata[0], newdata)
    print(result4, index)

猜你喜欢

转载自blog.csdn.net/qq_39858278/article/details/83034908