给定一个索引和一个大小,有没有更高效的方法来生成标准基向量:
import numpy as np
np.array([1.0 if i == index else 0.0 for i in range(size)])
In [2]: import numpy as np
In [9]: size = 5
In [10]: index = 2
In [11]: np.eye(1,size,index)
Out[11]: array([[ 0., 0., 1., 0., 0.]])
哎呀,不幸的是,使用np.eye进行此操作相当慢:
In [12]: %timeit np.eye(1,size,index)
100000 loops, best of 3: 7.68 us per loop
In [13]: %timeit a = np.zeros(size); a[index] = 1.0
1000000 loops, best of 3: 1.53 us per loop
将np.zeros(size); a[index] = 1.0
封装成一个函数只会带来一点点改善,但仍然比np.eye
要快得多:
In [24]: def f(size, index):
....: arr = np.zeros(size)
....: arr[index] = 1.0
....: return arr
....:
In [27]: %timeit f(size, index)
1000000 loops, best of 3: 1.79 us per loop
x = np.zeros(size)
x[index] = 1.0
>>> t = timeit.Timer('np.array([1.0 if i == index else 0.0 for i in range(size)]
)','import numpy as np;size=10000;index=5123')
>>> t.timeit(10)
0.039461429317952934 #original method
>>> t = timeit.Timer('x=np.zeros(size);x[index]=1.0','import numpy as np;size=10000;index=5123')
>>> t.timeit(10)
9.4077963240124518e-05 #zeros method
>>> t = timeit.Timer('x=np.eye(1.0,size,index)','import numpy as np;size=10000;index=5123')
>>> t.timeit(10)
0.0001398340635319073 #eye method
看起来np.zeros是最快的...
我不确定这样是否更快,但对于我来说肯定更清晰易懂。
a = np.zeros(size)
a[index] = 1.0
通常,你不仅需要一个基向量,而是需要所有的基向量。如果是这种情况,请考虑使用np.eye
:
basis = np.eye(3)
for vector in basis:
...
虽然不完全相同,但有密切关联:通过一些技巧,这甚至可以用来获取一组基矩阵:
>>> d, e = 2, 3 # want 2x3 matrices
>>> basis = np.eye(d*e,d*e).reshape((d*e,d,e))
>>> print(basis)
[[[ 1. 0. 0.]
[ 0. 0. 0.]]
[[ 0. 1. 0.]
[ 0. 0. 0.]]
[[ 0. 0. 1.]
[ 0. 0. 0.]]
[[ 0. 0. 0.]
[ 1. 0. 0.]]
[[ 0. 0. 0.]
[ 0. 1. 0.]]
[[ 0. 0. 0.]
[ 0. 0. 1.]]]
等等。
另一种实现方法如下:
>>> def f(size, index): ... return (np.arange(size) == index).astype(float) ...
这种方法的执行速度略慢:
>>> timeit.timeit('f(size, index)', 'from __main__ import f, size, index', number=1000000) 2.2554846050043125
eye
来实现这一点(因为名称暗示它是单位矩阵,而这绝对不是一个单位矩阵)。比我的答案更好的回答加1。 - mgilson