我发现程序中的瓶颈是从给定值列表中创建numpy数组的,最常见的是将四个值放入2x2数组中。有一种明显的,易于阅读的方法:
my_array = numpy.array([[1, 3], [2.4, -1]])
我们需要15次我们 - 非常慢,因为我做了数百万次。
那么,有一种更快,难以读的方式:
my_array = numpy.empty((2,2))
my_array[0,0] = 1
my_array[0,1] = 3
my_array[1,0] = 2.4
my_array[1,1] = -1
这速度快10倍,只有1个美国。
有什么方法既快速又易于阅读?
我到目前为止尝试的是:使用asarray
代替array
没有区别;将dtype=float
传递到array
也没有区别。最后,我知道我可以自己做:
def make_array_from_list(the_list, num_rows, num_cols):
the_array = np.empty((num_rows, num_cols))
for i in range(num_rows):
for j in range(num_cols):
the_array[i,j] = the_list[i][j]
return the_array
这将在4US中创建数组,这是中等速度的中等可读性(与上面的两种方法相比)。但实际上,我不敢相信使用内置方法没有更好的方法。
预先感谢您!
这是一个很好的问题。我找不到任何可以接近您完全展开的解决方案的速度的东西( edit @birico能够提出一些近距离。请参阅评论并更新 :)。以下是我(和其他)提出的许多不同选项和关联的时间:
import numpy as np
def f1():
"np.array + nested lists"
my_array = np.array([[1, 3], [2.4, -1]])
def f2():
"np.array + nested tuples"
my_array = np.array(((1, 3), (2.4, -1)))
def f3():
"Completely unrolled"
my_array = np.empty((2,2),dtype=float)
my_array[0,0] = 1
my_array[0,1] = 3
my_array[1,0] = 2.4
my_array[1,1] = -1
def f4():
"empty + ravel + list"
my_array = np.empty((2,2),dtype=float)
my_array.ravel()[:] = [1,3,2.4,-1]
def f5():
"empty + ravel + tuple"
my_array = np.empty((2,2),dtype=float)
my_array.ravel()[:] = (1,3,2.4,-1)
def f6():
"empty + slice assignment"
my_array = np.empty((2,2),dtype=float)
my_array[0,:] = (1,3)
my_array[1,:] = (2.4,-1)
def f7():
"empty + index assignment"
my_array = np.empty((2,2),dtype=float)
my_array[0] = (1,3)
my_array[1] = (2.4,-1)
def f8():
"np.array + flat list + reshape"
my_array = np.array([1, 3, 2.4, -1]).reshape((2,2))
def f9():
"np.empty + ndarray.flat (Pierre GM)"
my_array = np.empty((2,2), dtype=float)
my_array.flat = (1,3,2.4,-1)
def f10():
"np.fromiter (Bi Roco)"
my_array = np.fromiter((1,3,2.4,-1), dtype=float).reshape((2,2))
import timeit
results = {}
for i in range(1,11):
func_name = 'f%d'%i
my_import = 'from __main__ import %s'%func_name
func_doc = globals()[func_name].__doc__
results[func_name] = (timeit.timeit(func_name+'()',
my_import,
number=100000),
't'.join((func_name,func_doc)))
for result in sorted(results.values()):
print 't'.join(map(str,result))
和重要时机:
在Ubuntu Linux上,核心i7:
0.158674955368 f3 Completely unrolled
0.225094795227 f10 np.fromiter (Bi Roco)
0.737828969955 f8 np.array + flat list + reshape
0.782918930054 f5 empty + ravel + tuple
0.786983013153 f9 np.empty + ndarray.flat (Pierre GM)
0.814703941345 f4 empty + ravel + list
1.2375421524 f7 empty + index assignment
1.32230591774 f2 np.array + nested tuples
1.3752617836 f6 empty + slice assignment
1.39459013939 f1 np.array + nested lists
尽管显然是违反直觉的,但结果并不奇怪:Numpy并非设计用于处理大量非常小的数组。相反,它旨在操纵较大的数据阵列。
我建议先创建一个大型数组,大小为N*2*2
,用数据填充,然后将其重塑为(N,2,2)
。
作为旁注,您可能需要尝试
def f10():
mine = np.empty((2,2), dtype=float)
mine.flat = (1,3,2.4,-1)
.flat
方法应该比.ravel()[:]=...
方法高得多(我的个人测试显示与@mgilson f3
的顺序相同)。