【发布时间】:2015-08-03 07:50:30
【问题描述】:
我的矩阵的每个单元格都需要是由一个昂贵的函数计算的分数。矩阵是对称的,这是我能想到的填充每个单元格的最佳方法。
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
【问题讨论】:
-
很难说没有更多细节是什么让代码变慢了。 Python 循环很慢,但它可能不是瓶颈。话虽如此,
slow对你来说是什么?毫秒、秒、分钟……?你如何评价ExpensiveFunction()?它是否有任何参数,或者任何条目都是相同的函数调用? -
你的功能是什么?
-
ExpensiveFunction 有 5 个参数(3 个在循环之外定义,2 个以 CasesX 和 CasesY 为条件),它通过评估 R 代码(使用 python 包 rpy2)来计算相似度分数。慢,是相对的,同意,问题更多是关于嵌套 for 循环的效率,作为消除对称矩阵中一半计算的最佳方法。不知道 pandas 或 numpy 是否有一个巧妙的电话可以为您处理这个问题。
-
在 NumPy 中,您会尝试将 ExpensiveFunction 向量化并只调用一次。在实践中,这通常比通过每次调用一次函数来避免一半调用要快,因为迭代和索引在 Python 中很慢,但在本机代码中却很快(即矢量化代码在引擎盖下迭代)。您也许可以在 R 中进行矢量化。
-
ExpensiveFunction(x)是否仅取决于值x,还是也取决于[i,j]坐标。例如,它能否应用于阵列的扁平化版本?有一些工具可以索引数组的三角形部分。
标签: python numpy optimization matrix