【问题标题】:Improving the execution time of matrix calculations in Python提高 Python 中矩阵计算的执行时间
【发布时间】:2015-06-05 12:51:26
【问题描述】:

我处理大量数据,这段代码的执行时间非常重要。每次迭代的结果都是相互依赖的,所以很难并行。如果有更快的方法来实现这段代码的某些部分,那就太棒了,比如:

  • 查找矩阵中的最大元素及其索引
  • 将行/列中的值更改为另一行/列的最大值
  • 删除特定的行和列

填充weights 矩阵非常快。

代码执行以下操作:

  • 它包含单词列表word_list,其中包含count 元素。在开始时,每个单词都是一个单独的列表。
  • 它包含浮点值weights(下三角矩阵,i>=j 的值为零)的二维列表 (count x count)
  • 在每次迭代中,它执行以下操作:
    • 它会找到值最相似的两个单词(矩阵中的最大元素及其索引)
    • 它将它们的行和列合并,保存每个单元格中两者中较大的值
    • 它合并word_list中的相应单词列表。它将两个列表保存在具有较小索引 (max_j) 的列表中,并删除具有较大索引 (max_i) 的列表。
  • 如果最大值小于给定的THRESHOLD,它将停止

我可能会想出一种不同的算法来完成这项任务,但我目前还没有想法,如果至少有一点性能提升就很好了。

我尝试使用 NumPy,但效果更差。

weights = fill_matrix(count, N, word_list)
while 1:
    # find the max element in the matrix and its indices 
    max_element = 0
    for i in range(count):
        max_e = max(weights[i])
        if max_e > max_element:
            max_element = max_e
            max_i = i
            max_j = weights[i].index(max_e)

    if max_element < THRESHOLD:
        break

    # reset the value of the max element
    weights[max_i][max_j] = 0

    # here it is important that always max_j is less than max i (since it's a lower triangular matrix)
    for j in range(count):
        weights[max_j][j] = max(weights[max_i][j], weights[max_j][j])

    for i in range(count):
        weights[i][max_j] = max(weights[i][max_j], weights[i][max_i])

    # compare the symmetrical elements, set the ones above to 0
    for i in range(count):
        for j in range(count):
            if i <= j:
                if weights[i][j] > weights[j][i]:
                    weights[j][i] = weights[i][j]
                weights[i][j] = 0

    # remove the max_i-th column
    for i in range(len(weights)):
        weights[i].pop(max_i)

    # remove the max_j-th row
    weights.pop(max_i)

    new_list = word_list[max_j]
    new_list += word_list[max_i]
    word_list[max_j] = new_list

    # remove the element that was recently merged into a cluster
    word_list.pop(max_i)
    count -= 1

【问题讨论】:

  • 当您说您尝试使用 numpy 时,您是否只是将 weights 存储为 numpy 矩阵并保持代码不变,还是使用了 numpy 函数(通常很快)?例如,您的第一个循环可能是max_idx = numpy.argmax(weights); max_i, max_j = numpy.unravel_index(max_el_idx,weights.shape)。同样,您的第一个 j in range(count) 循环可能变为 weights[max_j,:] = numpy.maximum(weights[max_i,:],weights[max_j,:])。如果您小心使用内置函数和矢量化操作(一次处理整个数组),您可能会有所收获。
  • 如果您添加了一个 small 这个word_listweights 的示例,这将有助于使您的帖子更加清晰(足以让您的算法实际上给出有意义的结果) .我相当肯定它可以用 numpy 大大优化。

标签: python python-3.x optimization numpy


【解决方案1】:

这取决于您要投入多少工作,但如果您真的关心速度,您应该查看Cythonquick start tutorial 给出了一些示例,从 35% 加速到惊人的 150 倍加速(您需要付出一些额外的努力)。

【讨论】:

    【解决方案2】:

    这可能会有所帮助:

    def max_ij(A):
        t1 = [max(list(enumerate(row)), key=lambda r: r[1]) for row in A]
        t2 = max(list(enumerate(t1)), key=lambda r:r[1][1])
        i, (j, max_) = t2
        return max_, i, j
    

    【讨论】:

      猜你喜欢
      • 2018-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-11
      • 1970-01-01
      • 1970-01-01
      • 2018-08-01
      相关资源
      最近更新 更多