当我在里面使用两个循环时,我如何提高我的算法的效率?



经验丰富的朋友们,我提出了一种解决算法问题的方法。然而,我发现我的方法变得非常耗时当数据量增长时。请问有更好的方法来解决这个问题吗?有可能使用矩阵操作吗?

:

  • 假设有1个score-matrix和3个value-matrix
  • 每个square matrix都是相同大小的(N*N)
  • score-matrix中的元素表示两个实体之间的weights。例如,S12表示entity 1entity 2之间的分数。(权重只有在大于0时才有意义)
  • value-matrix中的元素表示两个实体之间的values。例如,"V12"表示entity 1~entity 2之间的值。因为我们有3个value-matrix,我们有3个不同的V12

目标是:我想将values与相应的weights相乘,这样我就可以最终输出一个(Nx3)矩阵。

我的解决方案:我解决了这个问题如下。然而,我在这里使用了两个for循环,这使得我的程序变得非常耗时. (例如N变大或者3变成100)请问这个代码有什么改进的方法吗?任何建议或提示将非常感激。提前感谢!

# generate sample data
import numpy as np
score_mat = np.random.randint(low=0, high=4, size=(2,2))
value_mat = np.random.randn(3,2,2)
# solve problem
# init the output info
output = np.zeros((2, 3))
# update the output info
for entity_1 in range(2):
# consider meaningful score
entity_others_list = np.where(score_mat[entity_1,:]>0)[0].tolist()
# iterate every other entity
for entity_2 in entity_others_list:
vec = value_mat[:,entity_1,entity_2].copy()
vec *= score_mat[entity_1,entity_2]
output[entity_1] += vec

您不需要手动迭代它们,只需将score_mat乘以value_mat,然后在axis=2上调用sum,在axis=1上再次调用sum

正如您所提到的,score只有在大于0时才有意义,如果是这种情况,您可以首先用1替换非正值,因为将某项乘以1保持不变:

>>> score_mat[score_mat<=0] = 1
>>> (score_mat*value_mat).sum(axis=2).sum(axis=1)
array([-0.58826032, -3.08093186, 10.47858256])

故障:

# This is what the randomly generated numpy arrays look like:
>>> score_mat
array([[3, 3],
[1, 3]])
>>> value_mat
array([[[ 0.81935985,  0.92228075],
[ 1.07754964, -2.29691059]],
[[ 0.12355602, -0.36182607],
[ 0.49918847, -0.95510339]],
[[ 2.43514089,  1.17296263],
[-0.81233976,  0.15553725]]])
# When you multiply the matcrices, each inner matrices in value_mat will be multiplied
# element-wise by score_mat
>>> score_mat*value_mat
array([[[ 2.45807955,  2.76684225],
[ 1.07754964, -6.89073177]],
[[ 0.37066806, -1.08547821],
[ 0.49918847, -2.86531018]],
[[ 7.30542266,  3.51888789],
[-0.81233976,  0.46661176]]])
# Now calling sum on axis=2, will give the sum of each rows in the inner-most matrices
>>> (score_mat*value_mat).sum(axis=2)
array([[ 5.22492181, -5.81318213],
[-0.71481015, -2.36612171],
[10.82431055, -0.34572799]])
# Finally calling sum on axis=1, will again sum the row values
>>> (score_mat*value_mat).sum(axis=2).sum(axis=1)
array([-0.58826032, -3.08093186, 10.47858256])

最新更新