提高Python中矩阵计算的执行时间

提高Python中矩阵计算的执行时间,python,python-3.x,optimization,numpy,Python,Python 3.x,Optimization,Numpy,我处理大量数据,这段代码的执行时间非常重要。每次迭代的结果都是相互依赖的,因此很难并行进行。如果有一种更快的方法来实现这段代码的某些部分,那就太棒了,比如: 求矩阵中的最大元素及其指数 使用另一行/列的最大值更改行/列中的值 删除特定的行和列 填充权重矩阵非常快 该代码执行以下操作: 它包含一个单词列表word\u list,其中包含count元素。在开头,每个单词都是一个单独的列表 它包含浮点值的二维列表(countxcount)weights(下三角矩阵,i>=j的值为零) 在每次迭代

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

  • 求矩阵中的最大元素及其指数
  • 使用另一行/列的最大值更改行/列中的值
  • 删除特定的行和列
填充
权重
矩阵非常快

该代码执行以下操作:

  • 它包含一个单词列表
    word\u list
    ,其中包含
    count
    元素。在开头,每个单词都是一个单独的列表
  • 它包含浮点值的二维列表(
    count
    x
    count
    weights
    (下三角矩阵,
    i>=j
    的值为零)
  • 在每次迭代中,它执行以下操作:
    • 它查找值最相似的两个单词(矩阵中的max元素及其索引)
    • 它合并它们的行和列,在每个单元格中保存两个较大的值
    • 它合并
      word\u list
      中相应的单词列表。它将两个列表保存在索引较小的列表中(
      max_j
      ),并删除索引较大的列表(
      max_i
  • 如果最大值小于给定的
    阈值
我可能会想到一种不同的算法来完成这项任务,但我现在还没有想法,如果至少有一点性能改进,那就太好了

我试过使用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
weights=填充矩阵(计数,N,单词列表)
而1:
#求矩阵中的最大元素及其索引
最大元素=0
对于范围内的i(计数):
最大值=最大值(重量[i])
如果最大元素>最大元素:
最大元素=最大元素
max_i=i
max_j=权重[i]。索引(max_e)
如果最大元素<阈值:
打破
#重置max元素的值
权重[max_i][max_j]=0
#这里重要的是,max_j总是小于max i(因为它是一个下三角矩阵)
对于范围内的j(计数):
权重[max_j][j]=max(权重[max_i][j],权重[max_j][j])
对于范围内的i(计数):
权重[i][max_j]=max(权重[i][max_j],权重[i][max_i])
#比较对称元素,将上面的元素设置为0
对于范围内的i(计数):
对于范围内的j(计数):
如果我称[j][i]:
权重[j][i]=权重[i][j]
权重[i][j]=0
#移除第i列的最大值
对于范围内的i(len(重量)):
权重[i].pop(最大值i)
#拆下第j行的max_
重量。pop(最大值)
新列表=单词列表[max\u j]
新列表+=单词列表[最大值]
单词列表[max\u j]=新列表
#删除最近合并到集群中的元素
单词列表.pop(max_i)
计数-=1

这取决于你想投入多少精力,但如果你真的关心速度,你应该考虑一下。给出了一些例子,从35%的加速到令人惊讶的150倍加速(您需要付出一些额外的努力)

这可能会有帮助:

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

当您说您尝试使用numpy时,是将
权重
存储为numpy矩阵并保持代码不变,还是使用了numpy函数(通常非常快)?例如,第一个循环可以是
max\u idx=numpy.argmax(权重);max_i,max_j=numpy.unlavel_索引(max_el_idx,weights.shape)
。类似地,范围(计数)循环中的第一个
j可能变成
weights[max\u j,:]=numpy.max(weights[max\u i,:],weights[max\u j,:])
。如果你小心地使用内置函数和向量化操作(一次处理整个数组),你可能会得到一些好处。如果你添加了一个
单词列表
权重
(刚好足够让你的算法实际给出有意义的结果)的小例子,这将有助于你的文章的清晰度。我相当肯定它可以大大优化与numpy。