我的矩阵的每个单元格需要是由昂贵函数计算的分数。矩阵是对称的,这是我能想到填充每个单元格的最佳方法。
num_cases = len(case_dictionary.keys()) # num_cases = 10
SmallMatrix = np.zeros((num_cases,num_cases))
for CasesX in range(0,num_cases):
for CasesY in range(CasesX,num_cases):
SmallMatrix[CasesX,CasesY] = 1
返回:
array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 0., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 0., 0., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 0., 0., 0., 1., 1., 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 1., 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0., 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0., 0., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
很容易......
但是,当Matrix更大且计算成本高时: 嵌套for循环是最有效的解决方案吗?
num_cases = len(case_dictionary.keys()) # 100000
BigMatrix = np.zeros((num_cases,num_cases))
for CasesX in range(0,num_cases):
for CasesY in range(CasesX,num_cases):
BigMatrix[CasesX,CasesY] = ExpensiveFunction()
慢...由于我的功能或循环?
修改
继续使用成对数据,所以我回去尝试使用@hpaulj解决方案。我不够了解为什么testUpper()更快?
def testUpper(func):
num_cases = 100
BigMatrix = np.zeros((num_cases,num_cases))
upper = np.triu_indices_from(BigMatrix)
BigMatrix[upper] = ExpensiveFunction()
从下面对@unutbu test
函数进行基准测试,针对numpy版本:
In [8]: %timeit test(ExpensiveFunction)
1 loops, best of 3: 11.1 s per loop
In [9]: %timeit testUpper(ExpensiveFunction)
1000 loops, best of 3: 2.03 ms per loop
答案 0 :(得分:5)
这是一个简单的实验,表明瓶颈更可能是ExpensiveFunction
:
import time
def SimpleFunction():
return 1
def ExpensiveFunction():
time.sleep(0.001)
return 1
def test(func):
num_cases = 100
BigMatrix = np.zeros((num_cases,num_cases))
for CasesX in range(0,num_cases):
for CasesY in range(CasesX,num_cases):
BigMatrix[CasesX,CasesY] = func()
In [84]: %timeit test(ExpensiveFunction)
1 loops, best of 3: 5.48 s per loop
In [85]: %timeit test(SimpleFunction)
1000 loops, best of 3: 890 µs per loop
除了被调用的函数之外,两个timeit运行是相同的。
当func
为SimpleFunction
时,填充BigMatrix
的时间不会超过1毫秒。
但当func
为ExpensiveFunction
时,填充BigMatrix
需要超过5秒。
所以双for-loop
可能不是瓶颈; ExpensiveFunction
是。您可以使用实际代码进行尝试以确保。如果事实证明ExpensiveFunction
是瓶颈,那么您就不需要打扰优化双循环,因为即使有更快的方式填充BigMatrix
- 即使您可以将时间成本减少到零 - 你会(在上面的例子中)只保存最多890 us
,而整个程序仍然需要超过5秒。
答案 1 :(得分:1)
我建议在你的矩阵的一半上应用你的“昂贵”计算,而不是使用symmetrize()
函数使你的numpy数组对称,这应该是最小的时间成本
def symmetrize(a):
return a + a.T - numpy.diag(a.diagonal())