我想生成一个二维的
编辑1:在应用“索引矩阵”技巧后,代码变得更快了,因此我想问的主要问题是是否有一种方法不使用这个技巧,因为它需要更多的内存。简而言之,我希望有一个既时间高效又空间高效的解决方案。
编辑2:以下是我测试过的一些例子。
numpy
数组,其中的元素是由它们的位置计算得出的。就像以下代码一样:import numpy as np
def calculate_element(i, j, other_parameters):
# do something
return value_at_i_j
def main():
arr = np.zeros((M, N)) # (M, N) is the shape of the array
for i in range(M):
for j in range(N):
arr[i][j] = calculate_element(i, j, ...)
由于Python中的循环效率不高,因此此代码运行非常缓慢。在这种情况下有没有更快的方法?
顺便说一下,现在我使用一个变通方法通过计算两个2D的“索引矩阵”来完成。就像这样:
def main():
index_matrix_i = np.array([range(M)] * N).T
index_matrix_j = np.array([range(N)] * M)
'''
index_matrix_i is like
[[0,0,0,...],
[1,1,1,...],
[2,2,2,...],
...
]
index_matrix_j is like
[[0,1,2,...],
[0,1,2,...],
[0,1,2,...],
...
]
'''
arr = calculate_element(index_matrix_i, index_matrix_j, ...)
编辑1:在应用“索引矩阵”技巧后,代码变得更快了,因此我想问的主要问题是是否有一种方法不使用这个技巧,因为它需要更多的内存。简而言之,我希望有一个既时间高效又空间高效的解决方案。
编辑2:以下是我测试过的一些例子。
# a simple 2D Gaussian
def calculate_element(i, j, i_mid, j_mid, i_sig, j_sig):
gaus_i = np.exp(-((i - i_mid)**2) / (2 * i_sig**2))
gaus_j = np.exp(-((j - j_mid)**2) / (2 * j_sig**2))
return gaus_i * gaus_j
# size of M, N
M, N = 1200, 4000
# use for loops to go through every element
# this code takes ~10 seconds
def main_1():
arr = np.zeros((M, N)) # (M, N) is the shape of the array
for i in range(M):
for j in range(N):
arr[i][j] = calculate_element(i, j, 600, 2000, 300, 500)
# print(arr)
plt.figure(figsize=(8, 5))
plt.imshow(arr, aspect='auto', origin='lower')
plt.show()
# use index matrices
# this code takes <1 second
def main_2():
index_matrix_i = np.array([range(M)] * N).T
index_matrix_j = np.array([range(N)] * M)
arr = calculate_element(index_matrix_i, index_matrix_j, 600, 2000, 300, 500)
# print(arr)
plt.figure(figsize=(8, 5))
plt.imshow(arr, aspect='auto', origin='lower')
plt.show()
calculate_element
的主体是什么?无论你如何分配,你仍然会调用这个函数 M*N 次。如果你可以缓存这个函数的中间结果,你就可以加速循环。 - JeremyM * N * np.intp
),使用numba
可以轻松避免。但是,如果没有calculate_element
的主体和 N,M 的大小估计,那只是一个猜测。 - Michael Szczesnynumpy
方法可以处理或生成整个数组。因此,即使在临时缓冲区中,它们也可能占用大量内存。从形状和 dtype 很容易估算内存使用情况。迭代可以避免那些大型临时数组,但这不会改变最终结果的大小。但是你会失去速度 - 除非你在编译工具(如cython
或numba
)中实现循环。 - hpaulj