在Python中优化两个矩阵的直方图距离度量

时间:2015-01-15 12:33:53

标签: python algorithm optimization numpy matrix

我有两个矩阵AB,每个矩阵的大小为NxM,其中N是样本数,M是大小直方图箱。因此,每行代表该特定样本的直方图。

我想要做的是计算不同样本对的两个矩阵之间的chi-square距离。因此,矩阵A中的每一行都将与另一个矩阵B中的所有行进行比较,从而生成大小为C且{{1}的最终矩阵NxN }}对应于C[i,j]chi-square直方图之间的A[i]距离。

这是我完成工作的python代码:

B[j]

目前,对于def chi_square(histA,histB): esp = 1.e-10 d = sum((histA-histB)**2/(histA+histB+eps)) return 0.5*d def matrix_cost(A,B): a,_ = A.shape b,_ = B.shape C = zeros((a,b)) for i in xrange(a): for j in xrange(b): C[i,j] = chi_square(A[i],B[j]) return C 矩阵,整个过程需要0.1秒。

有没有办法改善这种表现?

我很感激任何想法或建议。

谢谢。

1 个答案:

答案 0 :(得分:1)

当然!我假设您正在使用numpy

如果你有可用的RAM,你可以使用broadcast数组,并使用numpy对这些数组上的操作进行有效的矢量化。

以下是:

Abroad = A[:,np.newaxis,:]  # prepared for broadcasting
C = np.sum((Abroad - B)**2/(Abroad + B), axis=-1)/2.

与您的算法相比,我的平台上的时序考虑因素显示速度增加了10倍。

比前一个选项使用更少RAM的较慢选项(但仍然比原始算法更快)只是将A行广播到2D数组中:

def new_way(A,B):
    C = np.empty((A.shape[0],B.shape[0]))
    for rowind, row in enumerate(A):
        C[rowind,:] = np.sum((row - B)**2/(row + B), axis=-1)/2.
    return C

这样做的优点是它可以运行形状(N,M)远大于(100,70)的数组。

如果您没有可用的内存,您还可以查看Theano将昂贵的for循环推送到C级别。与(100,70)数组和(1000,70)数组的第一个选项(不考虑初始编译时间)相比,我获得了2倍的速度增益:

import theano
import theano.tensor as T
X = T.matrix("X")
Y = T.matrix("Y")
results, updates = theano.scan(lambda x_i: ((x_i - Y)**2/(x_i+Y)).sum(axis=1)/2., sequences=X)
chi_square_norm = theano.function(inputs=[X, Y], outputs=[results])
chi_square_norm(A,B)  # same result