面向初学者的 Python Numpy 快速介绍

NumPy 是用 Python 和 C 编写的。NumPy 中的计算是由用 C 编写的部分完成的,这使得它们与普通 Python 代码相比非常快。

NumPy是一个 Python 库,主要用于处理数组。数组是在内存中彼此相邻存储的项目的集合。现在,只需将它们视为 Python 列表。

NumPy 是用 Python 和 C 编写的。NumPy 中的计算是由用 C 编写的部分完成的,这使得它们与普通 Python 代码相比非常快。

安装

确保PythonPip已安装在您的计算机上。然后打开命令提示符或终端并运行以下命令:

pip install numpy

使用 NumPy 创建数组

您可以使用numpy模块的array()函数创建一个 NumPy 数组,如下所示:

import numpy as np

arr = np.array([3, 5, 7, 9])
print(type(arr))

输出将如下所示:

<class 'numpy.ndarray'>

我们刚刚从 python 列表创建了一个 NumPy 数组。我们arr变量的类型是numpy.ndarray。这里ndarray代表N维数组。

NumPy 中的尺寸或轴

在 NumPy 中,维度称为(轴的复数)。我喜欢将轴视为可以存储物品的线。

一个简单的列表或一维数组可以被可视化为:

一维阵列的轴

我们现在来看看以下内容:

  1. 标量(0D 数组)
  2. 向量(一维数组)
  3. 矩阵(二维数组)
  4. 3D 阵列
  5. 4D 阵列

标量(0D 数组)

标量只是一个值。

import numpy as np

s = np.array(21)
print("Number of axes:", s.ndim)
print("Shape:", s.shape)
输出:
Number of axes: 0
Shape: ()

这里我们使用了 NumPy 数组的 2 个属性:

  • ndim:它返回数组中的维数(或轴数)。它在这里返回 0,因为值本身没有任何维度。
  • shape:它返回一个元组,其中包含沿数组每个轴的值的数量。由于标量有 0 个轴,因此它返回一个空元组。

向量(一维数组)

向量是值的集合。

import numpy as np

vec = np.array([-1, 2, 7, 9, 2])
print("Number of axes:", vec.ndim)
print("Shape:", vec.shape)
输出:
Number of axes: 1
Shape: (5,)

vec.shape[0]给我们向量中的值的数量,这里是 5。

矩阵(二维数组)

矩阵是向量的集合。

import numpy as np

mat = np.array([
    [1, 2, 3],
    [5, 6, 7]
])

print("Number of axes:", mat.ndim)
print("Shape:", mat.shape)
输出:
Number of axes: 2
Shape: (2, 3)

在这里,我们使用列表列表创建了一个 2×3 矩阵(2D 数组)。由于矩阵有 2 个轴,mat.shape元组包含两个值:第一个值是行数,第二个值是列数。

矩阵

二维数组中的每个项目(行)都是一个向量(一维数组)。

3D 阵列

3D 数组是矩阵的集合。

import numpy as np

t = np.array([
    [[1, 3, 9],
     [7, -6, 2]],

    [[2, 3, 5],
     [0, -2, -2]],

    [[9, 6, 2],
     [-7, -3, -12]],

    [[2, 4, 5],
     [-1, 9, 8]]
])

print("Number of axes:", t.ndim)
print("Shape:", t.shape)
输出:
Number of axes: 3
Shape: (4, 2, 3)

在这里,我们使用 4 个列表的列表创建了一个 3D 数组,这些列表本身包含 2 个列表。

3D 阵列

3D 数组中的每个项目都是一个矩阵(1D 数组)。请注意,数组中的最后一个矩阵是图像中最前面的。

4D 阵列

4D 阵列

看了上面的例子后,我们在这里看到了一个模式。n 维数组是 n-1 维数组的集合,对于 n > 0。我希望您现在对多维数组的可视化有了更好的了解。


访问数组元素

就像 Python 列表一样,NumPy 数组中的索引以 0 开头。

import numpy as np

vec = np.array([-3, 4, 6, 9, 8, 3])
print("vec - 4th value:", vec[3])

vec[3] = 19
print("vec - 4th value (changed):", vec[3])

mat = np.array([
    [2, 4, 6, 8],
    [10, 12, 14, 16]
])
print("mat - 1st row:", mat[0])
print("mat - 2nd row's 1st value:", mat[1, 0])
print("mat - last row's last value:", mat[-1, -1])
输出:
vec - 4th value: 9
vec - 4th value (changed): 19
mat - 1st row: [2 4 6 8]
mat - 2nd row's 1st value: 10
mat - last row's last value: 16

NumPy 数组也支持切片:

# continuing the above code

print("vec - 2nd to 4th:", vec[1:4])
print("mat - 1st rows 1st to 3rd values:", mat[0, 0:3])
print("mat - 2nd column:", mat[:, 1])
输出:
vec - 2nd to 4th: [4 6 9]
mat - 1st row's 1st to 3rd values: [2 4 6]
mat - 2nd column: [ 4 12]

在最后一个示例中,[:, 1]说“从所有行中获取第二个值”。因此,我们得到矩阵的第二列作为输出。

示例:4D 数组中的索引

4D 数组中的索引

假设我们要访问带圆圈的值。它位于第 2 个 3D 数组的最后一个矩阵的第 2 行第 2 列。这很多,所以慢慢来。

以下是访问它的方法:

arr[2, -1, 1, 1]

Python 与 NumPy

在文章的开头,我说过 NumPy 中的计算与普通的 Python 代码相比非常快。让我们看看有什么不同。

我们将创建两个列表,其中包含从 0 到 9,999,999 的 1000 万个数字,按元素添加它们并测量所花费的时间。我们将两个列表都转换为 NumPy 数组并执行相同的操作。

import numpy as np
import time

l1 = list(range(10000000))
l2 = list(range(10000000))
sum = []

then = time.time()
for i in range(len(l1)):
	sum.append(l1[i] + l2[i])

print(f"With just Python: {time.time() - then: .2f}s")

arr1 = np.array(l1)
arr2 = np.array(l2)

then = time.time()
sum = arr1 + arr2
print(f"With NumPy: {time.time() - then: .2f}s")
输出:
With just Python:  2.30s
With NumPy:  0.14s

在这种情况下,NumPy 比原始 Python 快 16 倍。0

注释

虽然numpy对于大型数组计算无疑更快,但您的示例引入了减速,人为地导致原始 python 添加看起来比实际慢。

通过使用append,您要求 python 动态调整实现 list 的底层数组的大小sum,这不是添加是否更快的问题的核心。相反,如果您执行以下操作:没有任何重击CSSCC#去HTMLObjective-C爪哇JavaScriptJSONPerlPHP电源外壳Python红宝石锈SQL打字稿YAML

sum_pre_allocated = [None for _ in range(10000000)]

then = time.time()
for i in range(len(l1)):
	sum_pre_allocated[i] = l1[i] + l2[i]

你会节省一些时间。诚然,numpy它的性能仍然比普通 Python 好很多,但它的戏剧性略低于 16 倍。

结果:

$ python3 numpy_test.py 

(... individual results ...)

avg numpy:  0.14s
avg python:  1.76s
avg optimized python:  1.52s

https://gist.github.com/logyball/fcc227616308a1a0ea475cbd929e1a93

发表评论

邮箱地址不会被公开。 必填项已用*标注