有没有办法评估函数/表达式中的数值运算(+, - ,/,*)的数量?
在示例中,我们来看一个简单的线性代数问题(Ax = b
):
A_data = np.array([[1, -4, 1],
[1, 6, -1],
[2, -1, 2]], dtype=float)
b_data = np.array([[7],
[13],
[5]], dtype=float)
接下来,让我们应用高斯消除程序:
def gauss_elim(A, b):
Ab = np.column_stack((A, b))
for k, pivot_row in enumerate(Ab[:-1]):
for row in Ab[k+1:]:
if pivot_row[k] != 0:
row[k:] = row[k:] - pivot_row[k:] * row[k]/pivot_row[k]
return Ab
结果是:
array([[ 1. , -4. , 1. , 7. ],
[ 0. , 10. , -2. , 6. ],
[ 0. , 0. , 1.4, -13.2]])
我如何计算操作?
注意:我知道可以事先用数学方法评估操作次数(即Gaussian elimination是O(n ^ 3))。
答案 0 :(得分:1)
我假设您正在尝试降低此处的复杂性以提高性能。在这篇文章中列出了 kill Gauss-elimination
的内循环broadcasting
的方法,给我们一个部分向量化的解决方案,就像这样 -
# Concatenate A and b into a single 2D array
Ab = np.concatenate((A,b),axis=1)
for k, pivot_row in enumerate(Ab[:-1]):
# Vectorized broadcasting magic happens here :
# Calculate offsets corresponding to "pivot_row[k:] * row[k]/pivot_row[k]"
offsets = (Ab[k+1:,k][:,None] * pivot_row[k:])/pivot_row[k]
# Update each row
Ab[k+1:,k:] -= offsets
运行时测试并验证输出 -
In [137]: def partvect_gauss_elim(A,b):
...: Ab = np.concatenate((A,b),axis=1)
...: for k, pivot_row in enumerate(Ab[:-1]):
...: offsets = (Ab[k+1:,k][:,None] * pivot_row[k:])/pivot_row[k]
...: Ab[k+1:,k:] -= offsets
...: return Ab
...:
...: def original_gauss_elim(A,b):
...: Ab = np.concatenate((A,b),axis=1)
...: for k, pivot_row in enumerate(Ab[:-1]):
...: for row in Ab[k+1:]:
...: if pivot_row[k] != 0:
...: row[k:] = row[k:] - pivot_row[k:] * row[k]/pivot_row[k]
...: return Ab
...:
In [138]: A = np.random.randint(0,9,(50,50))
...: b = np.random.randint(0,9,(50,1))
...:
In [139]: np.allclose(original_gauss_elim(A,b),partvect_gauss_elim(A,b))
Out[139]: True
In [140]: %timeit original_gauss_elim(A,b)
100 loops, best of 3: 12.1 ms per loop
In [141]: %timeit partvect_gauss_elim(A,b)
100 loops, best of 3: 2.56 ms per loop
答案 1 :(得分:1)
如果您可以花一点时间,它应该有一种方法:创建一类数字并覆盖基本的算术方法:__add__
,__mul__
,__sub__
,{ {1}}通过在其中嵌入一个计数器系统(例如与一些全局变量相关)。然后,您应该能够通过使用__div__
参数(在创建数组时)强制Numpy使用您的类型,以确保Numpy不会将您的数字转换为任何其他类型。我有时会为简单的任务而做;我从来没有和Numpy一起做过,但它应该可行。希望它可以提供帮助。