1.numpy的核心结构:ndarray。
import numpy as np
a=np.array([[0,1,2],[3,4,5],[6,7,8]],dtype=np.float32)
ndarray是numpy的核心数据结构。我们来看一下ndarray如何在内存中储存的:关于数组的描述信息保存在一个数据结构中,这个结构引用两个对象,一块用于保存数据的存储区域和一个用于描述元素类型的dtype对象。
数据存储区域保存着数组中所有元素的二进制数据,dtype对象则知道如何将元素的二进制数据转换为可用的值。数组的维数、大小等信息都保存在ndarray数组对象
的数据结构中。
2.numpy中的分片不会引起复制,只是创建view。
Paste_Image.png3.numpy优化。
避免不必要的数据拷贝
查看数组的内存地址
def id(x):
return x.array_interface['data'][0]
就地操作和隐式拷贝操作。
Paste_Image.png%timeit a = np.zeros(10000000)
a *= 2
10 loops, best of 3: 19.2 ms per loop
%timeit a = np.zeros(10000000)
b = a * 2
10 loops, best of 3: 42.6 ms per loop
重塑二维矩阵不涉及拷贝操作,除非被转置。
a = np.zeros((10, 10)); aid = id(a); aid
53423728
b = a.reshape((1, -1)); id(b) == aid
True
c = a.T.reshape((1, -1)); id(c) == aid
False
数组的flatten和revel方法将数组变为一个一维向量(铺平数组)。flatten方法总是返回一个拷贝后的副本,而revel方法只有当有必要时才返回一个拷贝后的副本(所以该方法要快得多,尤其是在大数组上进行操作时)。
d = a.flatten(); id(d) == aid
False
e = a.ravel(); id(e) == aid
True
%timeit a.flatten()
1000000 loops, best of 3: 881 ns per loop
%timeit a.ravel()
1000000 loops, best of 3: 294 ns per loop
在NumPy数组上进行高效的选择
- 创建一个具有很多行的数组。我们将沿第一维选择该数组的分片。
n, d = 100000, 100
a = np.random.random_sample((n, d)); aid = id(a)
b1 = a[::10]
b2 = a[np.arange(0, n, 10)]
np.array_equal(b1, b2)
True
id(b1) == aid, id(b2) == aid
(True, False)
%timeit a[::10]
1000000 loops, best of 3: 804 ns per loop
%timeit a[np.arange(0, n, 10)]
100 loops, best of 3: 14.1 ms per loop
替代花式索引:索引列表
i = np.arange(0, n, 10)
b1 = a[i]
b2 = np.take(a, i, axis=0)
np.array_equal(b1, b2)
True
%timeit a[i]
100 loops, best of 3: 13 ms per loop
%timeit np.take(a, i, axis=0)
100 loops, best of 3: 4.87 ms per loop
当沿一个轴进行选择的索引是通过一个布尔掩码向量指定时,compress函数可以作为花式索引的替代方案。
i = np.random.random_sample(n) < .5
b1 = a[i]
b2 = np.compress(i, a, axis=0)
np.array_equal(b1, b2)
True
%timeit a[i]
10 loops, best of 3: 59.8 ms per loop
%timeit np.compress(i, a, axis=0)
10 loops, best of 3: 24.1 ms per loop
网友评论