首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加速guassian EM算法

加速guassian EM算法
EN

Stack Overflow用户
提问于 2015-11-14 11:25:10
回答 1查看 274关注 0票数 1

与follows...it一样,我的python代码需要花费很长时间。一定有什么小把戏我能用吗?我正在分析的图片很小而且是灰度的..。

代码语言:javascript
复制
def gaussian_probability(x,mean,standard_dev):
        termA = 1.0 / (standard_dev*np.sqrt(2.0*np.pi))
        termB = np.exp(-((x - mean)**2.0)/(2.0*(standard_dev**2.0)))
        g = (termA*termB)
        return g
def sum_of_gaussians(x):
        return sum([self.mixing_coefficients[i] * 
                    gaussian_probability(x, self.means[i], self.variances[i]**0.5) 
                    for i in range(self.num_components)])
def expectation():
        dim = self.image_matrix.shape
        rows, cols = dim[0], dim[1]
        responsibilities = []
        for i in range(self.num_components):
            gamma_k = np.zeros([rows, cols])
            for j in range(rows):
                for k in range(cols):
                    p = (self.mixing_coefficients[i] *      
                         gaussian_probability(self.image_matrix[j,k],
                                              self.means[i], 
                                              self.variances[i]**0.5))
                    gamma_k[j,k] = p / sum_of_gaussians(self.image_matrix[j,k])
            responsibilities.append(gamma_k)
        return responsibilities

我只包括了期望步骤,因为当最大化步骤遍历矩阵责任数组的每个元素时,它似乎走得比较快(所以瓶颈可能是所有的gaussian_probability计算?)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-14 13:37:33

通过做两件事,你可以大大加快计算速度:

  • 不要计算每个循环中的规范化!正如目前所写的,对于包含M组件的NxN图像,您正在计算每个相关的计算N * N * M时间,从而导致O[N^4 M^2]算法!相反,您应该计算所有的元素一次,然后除以和,这将是O[N^2 M]
  • 使用numpy矢量化而不是显式循环。这可以用您设置代码的方式非常直接地完成。

本质上,您的expectation函数应该如下所示:

代码语言:javascript
复制
def expectation(self):
    responsibilities = (self.mixing_coefficients[:, None, None] *
                        gaussian_probability(self.image_matrix,
                                             self.means[:, None, None],
                                             self.variances[:, None, None] ** 0.5))
    return responsibilities / responsibilities.sum(0)

您没有提供完整的示例,所以我不得不即兴地检查并对其进行基准测试,但是下面是一个简单的例子:

代码语言:javascript
复制
import numpy as np

def gaussian_probability(x,mean,standard_dev):
    termA = 1.0 / (standard_dev*np.sqrt(2.0*np.pi))
    termB = np.exp(-((x - mean)**2.0)/(2.0*(standard_dev**2.0)))
    return termA * termB

class EM(object):
    def __init__(self, N=5):
        self.image_matrix = np.random.rand(20, 20)
        self.num_components = N
        self.mixing_coefficients = 1 + np.random.rand(N)
        self.means = 10 * np.random.rand(N)
        self.variances = np.ones(N)

    def sum_of_gaussians(self, x):
        return sum([self.mixing_coefficients[i] * 
                    gaussian_probability(x, self.means[i], self.variances[i]**0.5) 
                    for i in range(self.num_components)])

    def expectation(self):
        dim = self.image_matrix.shape
        rows, cols = dim[0], dim[1]
        responsibilities = []
        for i in range(self.num_components):
            gamma_k = np.zeros([rows, cols])
            for j in range(rows):
                for k in range(cols):
                    p = (self.mixing_coefficients[i] *      
                         gaussian_probability(self.image_matrix[j,k],
                                              self.means[i], 
                                              self.variances[i]**0.5))
                    gamma_k[j,k] = p / self.sum_of_gaussians(self.image_matrix[j,k])
            responsibilities.append(gamma_k)
        return responsibilities

    def expectation_fast(self):
        responsibilities = (self.mixing_coefficients[:, None, None] *
                            gaussian_probability(self.image_matrix,
                                                 self.means[:, None, None],
                                                 self.variances[:, None, None] ** 0.5))
        return responsibilities / responsibilities.sum(0)

现在,我们可以实例化对象并比较预期步骤的两个实现:

代码语言:javascript
复制
em = EM(5)
np.allclose(em.expectation(),
            em.expectation_fast())
# True

从时间上看,对于包含5个组件的20x20图像,我们的速度大约是1000倍:

代码语言:javascript
复制
%timeit em.expectation()
10 loops, best of 3: 65.9 ms per loop

%timeit em.expectation_fast()
10000 loops, best of 3: 74.5 µs per loop

这种改进将随着图像大小和组件数量的增加而增加。祝你好运!

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33707870

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档