经验丰富的朋友们,我提出了一种解决算法问题的方法。然而,我发现我的方法变得非常耗时当数据量增长时。请问有更好的方法来解决这个问题吗?有可能使用矩阵操作吗?
:
- 假设有1个
score-matrix
和3个value-matrix
。 - 每个
square matrix
都是相同大小的(N*N)
。 score-matrix
中的元素表示两个实体之间的weights
。例如,S12
表示entity 1
和entity 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])