如何加快 numpy 查找速度并使其对内存更友好



我是numpy的新手,用谷歌搜索了很多,但是我(目前)很难加快我的代码速度。我尽可能使用 @profile 和 numba 优化我的代码。但是我的代码对于大量文档来说仍然很慢,并且需要大量的内存空间。我很确定我没有以正确(快速)的方式使用 numpy。因为我想学习,我希望你们中的一些人可以帮助我改进我的代码。我的整个代码可以在以下位置找到:我在位桶上的代码非常慢的部分是文件 CreateMatrix.py(create_log_entropy_weight_matrix和__create_np_p_ij_matrix_forLEW)中的对数熵权重计算

您可以在此处查看两种方法的分析结果

这里有两种方法:

@profile

@jit
def create_log_entropy_weight_matrix(self, np_freq_matrix_ordered):
    print(' * Create Log-Entropy-Weight-Matrix')
    np_p_ij_matrix = self.__create_np_p_ij_matrix_forLEW(np_freq_matrix_ordered)
    np_p_ij_matrix_sum = np_p_ij_matrix.sum(0)
    np_log_entropy_weight_matrix = np.zeros(np_freq_matrix_ordered.shape, dtype=np.float32)
    n_doc = int(np_freq_matrix_ordered.shape[0])
    row_len, col_len = np_freq_matrix_ordered.shape
    negative_value = False
    
    for col_i, np_p_ij_matrix_sum_i in enumerate(np_p_ij_matrix_sum):
        for row_i in range(row_len):
            local_weight_i = math.log(np_freq_matrix_ordered[row_i][col_i] + 1)
            if not np_p_ij_matrix[row_i][col_i]:
                np_log_entropy_weight_matrix[row_i][col_i] = local_weight_i
            else:                
                global_weight_i = 1 + (np_p_ij_matrix_sum_i / math.log(n_doc))
                np_log_entropy_weight_matrix[row_i][col_i] = local_weight_i * global_weight_i
    #        if np_log_entropy_weight_matrix[row_i][col_i] < 0:
    #            negative_value = True
    #print(' - - test negative_value:', negative_value)
    return(np_log_entropy_weight_matrix)
#@profile
@jit
def __create_np_p_ij_matrix_forLEW(self, np_freq_matrix_ordered):
    np_freq_matrix_ordered_sum = np_freq_matrix_ordered.sum(0)
    np_p_ij_matrix = np.zeros(np_freq_matrix_ordered.shape, dtype=np.float32)
    row_len, col_len = np_freq_matrix_ordered.shape
    
    for col_i, ft_freq_sum_i in enumerate(np_freq_matrix_ordered_sum):
        for row_i in range(row_len):
            p_ij = division_lew(np_freq_matrix_ordered[row_i][col_i], ft_freq_sum_i)
            if p_ij:
                np_p_ij_matrix[row_i][col_i] = p_ij * math.log(p_ij)
    return(np_p_ij_matrix)
</code>
 

希望有人能帮助我改进我的代码:)

这是一个删除一个迭代级别的尝试:

doc_log = math.log(n_doc)
local_weight = np.log(np_freq_matrix_ordered + 1)
for col_i, np_p_ij_matrix_sum_i in enumerate(np_p_ij_matrix_sum):
    local_weight_j = local_weight[:, col_i]
    ind = np_p_ij_matrix[:, col_i]>0
    local_weight_j[ind] *= 1 + np_p_ij_matrix_sum_i[ind] / doc_log
    np_log_entropy_weight_matrix[:, col_i] = local_weight_j    

我没有运行任何测试;我只是通读了你的代码并替换了不必要的迭代内容。

在没有完全理解您的代码的情况下,它看起来像是在执行可以在一个 - *、+、log 等的整个数组上完成的事情。 唯一的if是 避免log(0) . 我用ind掩蔽替换了一个if

变量名称很长且具有描述性。 在某种程度上,这很好,但通常更容易阅读名称较短的代码。 区分np_p_ij_matrixnp_p_ij_matrix_sum_i比区分xy需要更多的注意力。

请注意,我还用[,]样式替换了[][]索引。不一定更快,但更容易阅读。

但是我还没有使用足够的numba来知道这些变化在哪里改善了它的响应。 numba 允许您使用迭代编码风格,使老式 MATLAB 编码器变白。

最新更新