矢量化数组数组的函数

时间:2015-11-14 23:11:54

标签: python numpy

我是代码矢量化的新手,我对所有内容的速度有多快感到非常兴奋,但我无法从这段代码中获得高速...

这是住房类......

class GaussianMixtureModel:
    def __init__(self, image_matrix, num_components, means=None):

        self.image_matrix = image_matrix
        self.num_components = num_components
        if(means is None):
            self.means = np.zeros(num_components)
        else:
            self.means = np.array(means)
        self.variances = np.zeros(num_components)
        self.mixing_coefficients = np.zeros(num_components)

以下是我迄今为止所做的工作:

def likelihood(self):
    def g2(x):

#N =~ 5
#self.mixing_coefficients = 1D, N items
#self.variances = 1D, N items
#self.means = 1D, N items

        mc = self.mixing_coefficients[:,None,None]
        std = self.variances[:,None,None] ** 0.5
        var = self.variances[:,None,None]
        mean = self.means[:,None,None]
        return np.log((mc*(1.0/(std*np.sqrt(2.0*np.pi)))*(np.exp(-((x-mean)**2.0)/(2.0*var)))).sum())

    f = np.vectorize(g2)

#self.image_matrix =~ 400*700 2D matrix

    log_likelihood = (f(self.image_matrix)).sum()
    return log_likelihood

以下是我得到的结果很奇怪(注意self.image_matrix是灰度图像的nxn矩阵):

def likelihood(self):
    def g2():

#N =~ 5
#self.mixing_coefficients = 1D, N items
#self.variances = 1D, N items
#self.means = 1D, N items
#self.image_matrix = 1D, 400x700 2D matrix

        mc = self.mixing_coefficients[:,None,None]
        std = self.variances[:,None,None] ** 0.5
        var = self.variances[:,None,None]
        mean = self.means[:,None,None]
        return np.log((mc*(1.0/(std*np.sqrt(2.0*np.pi)))*(np.exp(-((self.image_matrix-mean)**2.0)/(2.0*var)))).sum())

    log_likelihood = (g2()).sum()
    return log_likelihood

然而,与第一个版本相比,第二个版本真的快(这需要将近10秒......而且速度在这里非常重要,因为这是收敛算法的一部分)

有没有办法复制第一个版本的结果和第二个版本的速度? (我真的不熟悉矢量化以了解为什么第二个版本不起作用)

1 个答案:

答案 0 :(得分:2)

第二个版本速度非常快,因为它只使用self.image_matrix的第一个单元格:

return np.log((mc*(1.0/(std*np.sqrt(2.0*np.pi)))*(np.exp(-((self.image_matrix[0,0]-mean)**2.0)/(2.0*var)))).sum())
#                                                                            ^^^^^

这也是它完全错误的原因。它根本不是self.image_matrix上的矢量化计算。不要试图将其运行时作为比较点;你总是可以比正确的代码更快地制作错误的代码。

通过消除np.vectorize的使用,您可以使第一个版本更快,但不如错误的代码快。 sum内的log只需要指定适当的轴:

def likelihood(self):
    def f(x):
        mc = self.mixing_coefficients[:,None,None]
        std = self.variances[:,None,None] ** 0.5
        var = self.variances[:,None,None]
        mean = self.means[:,None,None]
        return np.log((mc*(1.0/(std*np.sqrt(2.0*np.pi)))*(np.exp(-((x-mean)**2.0)/(2.0*var)))).sum(axis=0))

    log_likelihood = (f(self.image_matrix)).sum()

这可以通过几种方式进一步简化和优化。例如,可以消除嵌套函数,乘以1.0/whatever比除whatever要慢,但消除np.vectorize是最重要的。