使用NumPy优化非数字矩阵的创建



当我试图找到一种方法来优化一个巨大的2D矩阵的创建和打印时,我决定尝试NumPy。但是,对我来说不幸的是,相反地使用这个库会使情况变得更糟。我的目标是创建一个矩阵,它将被带有索引的字符串填充。像这样(其中n是矩阵的大小):

python_matrix = [[f"{y}, {x}" for x in range(n)] for y in range(n)]

当我使用NumPy库的array()函数时:

numpy_matrix = numpy.array([[f"{y}, {x}" for x in range(n)] for y in range(n)])

创建矩阵的时间只会增加。例如,对于n = 1000:python_matrix的创建时间为0.032秒,numpy_matrix的创建时间为0.419秒,比python长13倍

而且,numpy_matrix的打印速度比python_matrix(使用for循环

)慢(如果您输出完整版本,而不是缩短版本)。
n = 1000
def numpy_matrix(n):
matrix = numpy.array([[f"{y}, {x}" for x in range(n)] for y in range(n)])
with numpy.printoptions(threshold=numpy.inf):
print(coordArr)
def python_matrix(n):
matrix = [[f"{y}, {x}" for x in range(n)] for y in range(n)]
def print_matrix():
for arr in matrix:
print(arr)
print_matrix()
# time of numpy_matrix > time of python_matrix
  1. 是使用标准的Python功能更好,还是NumPy实际上更高效,我只是没有正确使用它?
  2. 另外,如果我使用NumPy,如何加快矩阵完整版本输出的问题仍然存在

运行ipython会话和使用它的timeit,我没有得到这么大的差异:

制作列表:

In [13]: timeit [[f"{y}, {x}" for y in range(N)] for x in range(N)]
492 ms ± 3.28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

生成数组(同时生成列表):

In [14]: timeit np.array([[f"{y}, {x}" for y in range(N)] for x in range(N)])
779 ms ± 12.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

从时间中删除列表创建步骤:

In [15]: %%timeit alist = [[f"{y}, {x}" for y in range(N)] for x in range(N)]
...: np.array(alist)
...: 
...: 
313 ms ± 12.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

所以从一个已经存在的列表中创建数组的时间不会太长。

指定dtype也有帮助:

In [18]: %%timeit alist = [[f"{y}, {x}" for y in range(N)] for x in range(N)]
...: np.array(alist, dtype='U8')
...: 
...: 
224 ms ± 2.67 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

计时打印更尴尬,尽管我们可以计时字符串格式,str(x)。我不会显示时间,但是,数组格式化要慢得多。本质上,numpy必须通过Python自己的字符串处理代码;它没有自己的东西。

数字列表/数组

对于数字数组,相对差异更大:

In [29]: alist = [[(x,y) for y in range(N)] for x in range(N)]
In [30]: arr = np.array(alist)
In [31]: arr.shape
Out[31]: (1000, 1000, 2)
In [32]: timeit alist = [[(x,y) for y in range(N)] for x in range(N)]
171 ms ± 8.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [33]: timeit arr = np.array(alist)
832 ms ± 36.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

但是,如果使用数组方法创建相同的数组-即不是通过列表的列表,时间会好得多:

In [40]: timeit np.stack(np.broadcast_arrays(np.arange(N)[:,None], np.arange(N)),axis=2)
8.51 ms ± 89.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

numpy不是在所有方面对列表的改进。它最适合对现有数组进行数学运算。从列表创建数组非常耗时。而且它并没有为字符串处理添加太多内容。

最新更新