np.full(size, 0)与np.zeros(size)与np.empty()的区别在哪里?

33

如果你要选择以下三种方式之一来初始化一个零数组,你会选择哪一种,为什么

my_arr_1 = np.full(size, 0) 
或者
my_arr_2 = np.zeros(size)
或者
my_arr_3 = np.empty(size)
my_arr_3[:] = 0

1
这正是np.zeros的用途。你为什么不使用它呢? - Warren Weckesser
我实际上正在使用它。但是,我不确定这些方法中哪一种在时间和内存使用方面最有效! - Dataman
5个回答

21

我会使用np.zeros,因为它的名称。我绝不会使用第三种习惯用法,因为

  1. 它需要两个语句而不是一个单独的表达式

  2. 对于NumPy的开发人员来说更难进行优化。事实上,在NumPy 1.10中,尽管所有索引优化,np.zeros仍然是最快的选项:

>>> %timeit np.zeros(1e6)
1000 loops, best of 3: 804 µs per loop
>>> %timeit np.full(1e6, 0)
1000 loops, best of 3: 816 µs per loop
>>> %timeit a = np.empty(1e6); a[:] = 0
1000 loops, best of 3: 919 µs per loop

与@John Zwinck的结果进行比较的更大的数组:

>>> %timeit np.zeros(1e8)
100000 loops, best of 3: 9.66 µs per loop
>>> %timeit np.full(1e8, 0)
1 loops, best of 3: 614 ms per loop
>>> %timeit a = np.empty(1e8); a[:] = 0
1 loops, best of 3: 229 ms per loop

1
“full”和赋值是相同的,尽管我更喜欢提到我更喜欢a[...] = 0而不是a[:]。现在的zeros会告诉内核将内存清零。 - seberg
没有,但这并不在我的测量范围内 :) - seberg
根据此,以及1e6和1e8情况下的时间,我猜测np.zeros()最终会使用匿名的mmap(),超过某个阈值(np.empty()可能也会使用它,设置了MAP_UNINITIALIZED标志),并且在第一次读/写之前内存不会被清零,甚至不能正确分配,使得计时更或多或少无用。 (对于所有测量中的数组执行例如np.sum()可能会给出更合理的结果) - Aleksi Torhamo

9

毫无疑问是使用np.zeros。不仅是最常见和最符合惯用法的方式,而且速度也远超其他方法:

In [1]: size=100000000

In [3]: %timeit np.full(size, 0)
1 loops, best of 3: 344 ms per loop

In [4]: %timeit np.zeros(size)
100000 loops, best of 3: 8.75 µs per loop

In [5]: %timeit a = np.empty(size); a[:] = 0
1 loops, best of 3: 322 ms per loop

有趣的一点是:如果数组形状不是1D, - chris

7

np.zeros函数可以更快地将数组初始化为零。如果只想要初始化一个给定形状和类型的数组,但不关心数组中的初始条目,则使用np.empty会稍微更快一些。

以下是基本测试结果:

>>%timeit np.zeros(1000000)
7.89 µs ± 282 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

>>%timeit np.empty(1000000)
7.84 µs ± 332 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

你正在拿苹果和橙子进行比较。np.zeros(n)np.empty(n)的结果不同,这已经在@FredFoo的解决方案中解释过了。 - jpp
好的,谢谢你纠正我。所以如果只是初始化,np.empty会稍微快一点;如果要初始化为零,np.zero则会快得多。 - l001d
当然可以。但是有两个不同的问题:(1)不同的输出,(2)速度。实际上,只有(1)很重要。 - jpp
@jpp 我认为,如果我们不关心初始数组中的值,使用np.emptynp.zeros有什么优势。 - Jean Paul

2
np.zero():always 0
np.empty():Random number, depending on memory condition

最初的回答:

您可以查看以下以进行比较

np.zeros( (3,4) )
array([[ 0.,  0.,  0.,  0.],
...    [ 0.,  0.,  0.,  0.],
...    [ 0.,  0.,  0.,  0.]])


np.empty((3,4))
array([[1.13224202e+277, 1.73151846e-077, 1.24374310e-047,1.30455491e-076],
       [3.92384790e+179, 6.01353875e-154, 3.12452337e-033,7.72229932e+140],
       [1.28654694e-320, 0.00000000e+000, 0.00000000e+000,0.00000000e+000]])

0
首先,我们应该了解这三者之间的区别,以便选择其中之一。
  1. np.zeros(size): 生成一个给定形状的全0数组。
np.zeros(5)    #array([0., 0., 0., 0., 0.])
  • np.empty(5): empty 创建一个数组,其初始内容是随机的,并且取决于内存的状态。
  • np.empty(4)    #array([0.00000000e+000, 1.05915457e-311, 1.05915457e-311, 1.05915457e-311])
    
  • np.full(size, fill_value): 返回一个给定形状和类型的新数组,填充为fill_value。
  • np.full((2, 2), 10)      #array([[10, 10],
                                     [10, 10]])  
    

    所以,在这种情况下,np.zeros(size) 显然是正确的选择,也是创建一个填充有零的数组的快速方法。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接