跳到主要内容

Numpy 矩阵运算

信息
2024年8月10日 · ·

NumPy(Numerical Python)是 Python 中用于科学计算的一个开源库,它提供了一个强大的多维数组对象以及各种操作这些数组的函数;NumPy 可以被认为是 Python 科学计算的基础库之一;

NumPy 的主要特点

  • 多维数组对象:NumPy 提供了 ndarray 类型,是一个 n 维数组对象,可以储存同类型元素的集合(例如整数、浮点数等),与 Python 的原生列表相比,ndarray 对象占用更少的内存,支持更快的运算;

  • 广播功能:NumPy 支持在不同形状和大小的数组之间进行算术运算,这个功能称为广播;对于每个二进制 ufunc 操作(加减乘除等),它会尝试将两个输入向量转换成相同的形状并进行计算,使得您可以使用简单的代码来执行操作,而无需编写循环;

  • 转换功能:NumPy 提供了丰富的数据类型来表示数字,字符串和其他变量类型;这些数据类型可以用于 Numpy 数组中,它们定义了每个元素的大小和解释方式;此外,NumPy 还提供了许多方便的功能来从其他 Python 数据结构中创建数组;

  • 数学函数库:NumPy 内置了许多常见的数学函数,如三角函数、指数函数、对数函数等,还有一些高级数学函数,如线性代数、随机数生成器等;

  • 文件 I/O:NumPy 支持从和到磁盘读写数据和文件;

NumPy 是 Python 科学计算的重要工具,被广泛地应用于各种领域,如数据分析、机器学习、图像处理等;

引入 numpy

>>> import numpy as np

1. 数组的初始化

1. 使用 list 初始化数组

# 调用 np.array 从 list 初始化一个数据
>>> l = [1, 2, 3]
>>> print(type(l))
>>> print(l)
<class 'list'>
[1, 2, 3]

>>> a = np.array([1, 2, 3])
>>> print(type(a))
>>> print(a)
<class 'numpy.ndarray'>
[1 2 3]

>>> a
array([1, 2, 3])

>>> a[2]
3

>>> a[0] = 5
>>> a
array([5, 2, 3])

# 二维数组
>>> b = np.array([[1, 2, 3], [2, 3, 4]])
>>> b
array([[1, 2, 3],
[2, 3, 4]])

>>> type(b)
numpy.ndarray

# 数组的维度
>>> b.shape
(2, 3)

>>> b[0, 2]
3

2. 内置构建数组的函数

初始化一个以 0 填充的数组

>>> a = np.zeros((2, 3))
>>> a
array([[0., 0., 0.],
[0., 0., 0.]])

初始化一个以 1 填充的数组

>>> b = np.ones((1, 2))
>>> b
array([[1., 1.]])

初始化一个以自定义数(比如 8 )填充的数组

>>> c = np.full((2, 2), 8)
>>> c
array([[8, 8],
[8, 8]])

对角矩阵

>>> d = np.eye(3, k=1)
>>> d
array([[0., 1., 0.],
[0., 0., 1.],
[0., 0., 0.]])

随机数矩阵

>>> e = np.random.random((3, 2))
>>> e
array([[0.61689958, 0.48564929],
[0.50384802, 0.89786453],
[0.08463754, 0.9107176 ]])

没有被初始化值的矩阵

>>> f = np.empty((2, 3, 4))
>>> f
array([[[3.10503618e+231, 3.10503618e+231, 1.03753786e-322,
0.00000000e+000],
[0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
0.00000000e+000],
[0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
0.00000000e+000]],

[[0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
2.28093341e+243],
[3.10503618e+231, 3.10503618e+231, 6.42285340e-323,
0.00000000e+000],
[0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
0.00000000e+000]]])

等差数列

>>> g = np.arange(15)
>>> g
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

>>> g.shape
(15,)

>>> g.dtype
dtype('int64')

3. 指定数据类型的数组

# 不指定则自动匹配
>>> int_arr = np.array([1, 2, 3, 4, 5])
>>> '%s %s' % (int_arr, int_arr.dtype)
'[1 2 3 4 5] int64'

>>> float_arr = np.array([1, 2, 3, 4, 5], dtype=np.float64)
>>> '%s %s' % (float_arr, float_arr.dtype)
'[1. 2. 3. 4. 5.] float64'

4. 使用 astype 复制数组并转换数据类型

>>> float_arr = int_arr.astype(np.float64)
>>> '%s %s' % (float_arr, float_arr.dtype)
'[1. 2. 3. 4. 5.] float64'

# astype 将 float 转 int 时,会丢掉小数部分
>>> float_arr = np.array([3.5, 2.3, 3.4, -2.3])
>>> int_arr = float_arr.astype(np.int64)
>>> '%s(%s) => %s(%s)' % (float_arr, float_arr.dtype, int_arr, int_arr.dtype)
'[ 3.5 2.3 3.4 -2.3](float64) => [ 3 2 3 -2](int64)'

# astype 将字符串转数组,失败则抛异常
>>> str_arr = np.array(['1.2', '2.4', '5.6', 'asdfa'], dtype=np.string_)
>>> str_arr
array([b'1.2', b'2.4', b'5.6', b'asdfa'], dtype='|S5')

# float_arr = str_arr.astype(dtype=np.float64)
# float_arr

# astype 使用其他数组的数据类型作为参数
>>> int_arr = np.arange(10)
>>> float_arr = np.array([2.3, 4.5, 6.5])
>>> int_arr.astype(dtype = float_arr.dtype)
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

2. 数组的取值和赋值

>>> a = np.array([[1,2,3,4],[5,6,7,8],[9,10,12,11]])
>>> a
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 12, 11]])

1. 切片 - 对原数组对引用

# 多维数组从多个维度同时切片
>>> b = a[0:2, 2:4]
>>> b
array([[3, 4],
[7, 8]])

# 对切片出来的数组赋值, b 只是对a 切片区的引用,copy() 函数可以实现复制
>>> b[0, 0] = 9999
>>> b, a
(array([[9999, 4],
[ 7, 8]]),
array([[ 1, 2, 9999, 4],
[ 5, 6, 7, 8],
[ 9, 10, 12, 11]]))

# 取第一行,得到的是值
>>> row_1 = a[1, :]
>>> row_1, row_1.shape
(array([5, 6, 7, 8]), (4,))

# 切第一行,得到的是数组
>>> row_2 = a[1:2, :]
>>> row_2, row_2.shape
(array([[5, 6, 7, 8]]), (1, 4))

# [1] 与 1:2 效果一样
>>> row_3 = a[[0, 2], :]
>>> row_3, row_3.shape
(array([[ 1, 2, 9999, 4],
[ 9, 10, 12, 11]]),
(2, 4))

# 取第二个维度(列)的一列,结果还是行,只有一个维度
>>> col_1 = a[:, 1]
>>> col_1, col_1.shape
(array([ 2, 6, 10]), (3,))

# 对每一行的每一列切片
>>> col_2 = a[:, 1:2]
>>> col_2, col_2.shape
(array([[ 2],
[ 6],
[10]]),
(3, 1))

2. 通过下标 - 重建新数组

>>> a
array([[ 1, 2, 9999, 4],
[ 5, 6, 7, 8],
[ 9, 10, 12, 11]])

>>> b = a[[0, 1, 2, 2], [2, 1, 2, 3]]
>>> b, b.shape
(array([9999, 6, 12, 11]), (4,))

# 等同于这样:
>>> c = np.array([a[0, 2], a[1, 1], a[2, 2], a[2, 3]])
>>> c, c.shape
(array([9999, 6, 12, 11]), (4,))

# 取 (0, 0),(2, 1),(1, 2),(0, 3)
>>> i = np.array([0, 2, 1, 0])
>>> a[i, np.array(np.arange(4))]
array([ 1, 10, 7, 4])

# 对指定范围赋值
>>> a[i, np.array(np.arange(4))] += 10
>>> a
array([[ 11, 2, 9999, 14],
[ 5, 6, 17, 8],
[ 9, 20, 12, 11]])

3. 通过条件

>>> bool_index = a > 2
>>> bool_index, bool_index.shape
(array([[ True, False, True, True],
[ True, True, True, True],
[ True, True, True, True]]),
(3, 4))

>>> a[bool_index]
array([ 11, 9999, 14, 5, 6, 17, 8, 9, 20, 12, 11])

3. 数据类型

# 通过 dtype 看 numpy 的数组中元素的数据类型
>>> x = np.array([2, 1])
>>> y = np.array([1.0, 2.0])
>>> z = np.array([1, 2], dtype=np.float64)
>>> x.dtype, y.dtype, z.dtype
(dtype('int64'), dtype('float64'), dtype('float64'))

4. 数学运算

>>> x = np.array([[1, 2], [3, 4]])
>>> y = np.array([[5, 6], [7, 8]])
>>> x, y
(array([[1, 2],
[3, 4]]),
array([[5, 6],
[7, 8]]))

1. 逐元素相加

>>> x + y
array([[ 6, 8],
[10, 12]])

# 与上等同
>>> np.add(x, y)
array([[ 6, 8],
[10, 12]])

2. 逐元素相减

>>> x - y
array([[-4, -4],
[-4, -4]])

# 与上等同
>>> np.subtract(x, y)
array([[-4, -4],
[-4, -4]])

3. 逐元素相乘

>>> x * y
array([[ 5, 12],
[21, 32]])

# 与上等同
>>> np.multiply(x, y)
array([[ 5, 12],
[21, 32]])

4. 逐元素相除

>>> x/y
array([[0.2 , 0.33333333],
[0.42857143, 0.5 ]])

# 与上等同
>>> np.divide(x, y)
array([[0.2 , 0.33333333],
[0.42857143, 0.5 ]])

5. 逐元素求平方根

>>> np.sqrt(x)
array([[1. , 1.41421356],
[1.73205081, 2. ]])

6. 向量内积

>>> v = np.array([9, 10])
>>> w = np.array([10, 11])
>>> v.dot(w)
200

# 与上等同
>>> np.dot(v, w)
200

7. 矩阵乘法

>>> x
array([[1, 2],
[3, 4]])

>>> v.dot(x)
array([39, 58])

>>> x.dot(v)
array([29, 67])

>>> v.T, v
(array([ 9, 10]), array([ 9, 10]))

>>> x.dot(y)
array([[19, 22],
[43, 50]])

>>> y.dot(x)
array([[23, 34],
[31, 46]])

8. 矩阵转置

# 一维数组的转置是它自己
>>> v.T
array([ 9, 10])

# 二维数组的转置
>>> x.T
array([[1, 3],
[2, 4]])

9. 点积

>>> arr = np.random.random((6, 3))
>>> arr
array([[0.41381963, 0.87659293, 0.09424397],
[0.72492909, 0.33409919, 0.41864532],
[0.00455007, 0.56686201, 0.26810043],
[0.76566461, 0.59330859, 0.3293368 ],
[0.30364547, 0.07882817, 0.64756393],
[0.7907812 , 0.84248807, 0.01036639]])

>>> arr.T.dot(arr)
array([[2.00056734, 1.75196378, 0.80069698],
[1.75196378, 2.26938509, 0.62963679],
[0.80069698, 0.62963679, 0.7839329 ]])

>>> arr.dot(arr.T)
array([[0.94854377, 0.63231367, 0.52405699, 0.86797517, 0.25578366, 1.06673684],
[0.63231367, 0.81240836, 0.30492561, 0.89115178, 0.51755747, 0.85907472],
[0.52405699, 0.30492561, 0.39323108, 0.42810327, 0.21967847, 0.48395183],
[0.86797517, 0.89115178, 0.42810327, 1.04672011, 0.49252665, 1.10874262],
[0.25578366, 0.51755747, 0.21967847, 0.49252665, 0.51775349, 0.31324182],
[1.06673684, 0.85907472, 0.48395183, 1.10874262, 0.31324182, 1.33522852]])

10. 高维转置

>>> arr = np.arange(16).reshape(2, 2, 4)
>>> arr, arr.shape
(array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],

[[ 8, 9, 10, 11],
[12, 13, 14, 15]]]),
(2, 2, 4))

>>> arr.transpose(0, 1, 2)
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],

[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])

# 第1纬和第2纬转置
>>> arr.transpose(0, 2, 1)
array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]],

[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])

# 同上
>>> arr.swapaxes(1, 2)
array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]],

[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])

>>> arr.transpose(2, 1, 0)
array([[[ 0, 8],
[ 4, 12]],

[[ 1, 9],
[ 5, 13]],

[[ 2, 10],
[ 6, 14]],

[[ 3, 11],
[ 7, 15]]])

11. matmul 矩阵点乘

>>> x = np.arange(24).reshape(2, 3, 4)
>>> y = np.arange(8).reshape(4, 2)
>>> x, y

(array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],

[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]]),
array([[0, 1],
[2, 3],
[4, 5],
[6, 7]]))

>>> z = np.matmul(x, y)
>>> z, z.shape
(array([[[ 28, 34],
[ 76, 98],
[124, 162]],

[[172, 226],
[220, 290],
[268, 354]]]),
(2, 3, 2))

>>> z = x.dot(y)
>>> z, z.shape
(array([[[ 28, 34],
[ 76, 98],
[124, 162]],

[[172, 226],
[220, 290],
[268, 354]]]),
(2, 3, 2))

>>> x = np.arange(24).reshape(2,3,4)
>>> y = np.arange(16).reshape(2,4,2)
>>> z = np.matmul(x, y)
>>> z, z.shape
(array([[[ 28, 34],
[ 76, 98],
[ 124, 162]],

[[ 604, 658],
[ 780, 850],
[ 956, 1042]]]),
(2, 3, 2))

>>> z = np.dot(x,y)
>>> z, z.shape
(array([[[[ 28, 34],
[ 76, 82]],

[[ 76, 98],
[ 252, 274]],

[[ 124, 162],
[ 428, 466]]],


[[[ 172, 226],
[ 604, 658]],

[[ 220, 290],
[ 780, 850]],

[[ 268, 354],
[ 956, 1042]]]]),
(2, 3, 2, 2))

12. sum 矩阵求和

>>> x
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],

[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])

>>> np.sum(x)
276

>>> x.sum()
276

>>> np.sum(x, axis=0)
array([[12, 14, 16, 18],
[20, 22, 24, 26],
[28, 30, 32, 34]])

>>> x.sum(axis=0)
array([[12, 14, 16, 18],
[20, 22, 24, 26],
[28, 30, 32, 34]])

>>> np.sum(x, axis=0).sum(axis=0)
array([60, 66, 72, 78])

13. cumsum 矩阵累加

>>> x.cumsum(axis=0)
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],

[[12, 14, 16, 18],
[20, 22, 24, 26],
[28, 30, 32, 34]]])

>>> x.cumsum(axis=1)
array([[[ 0, 1, 2, 3],
[ 4, 6, 8, 10],
[12, 15, 18, 21]],

[[12, 13, 14, 15],
[28, 30, 32, 34],
[48, 51, 54, 57]]])

14. cumprod 矩阵累乘

>>> x.cumprod(axis=0)
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],

[[ 0, 13, 28, 45],
[ 64, 85, 108, 133],
[160, 189, 220, 253]]])

>>> x.cumprod(axis=1)
array([[[ 0, 1, 2, 3],
[ 0, 5, 12, 21],
[ 0, 45, 120, 231]],

[[ 12, 13, 14, 15],
[ 192, 221, 252, 285],
[3840, 4641, 5544, 6555]]])

15. mean 矩阵均值

>>> np.mean(x)
11.5

>>> np.mean(x, axis=0)
array([[ 6., 7., 8., 9.],
[10., 11., 12., 13.],
[14., 15., 16., 17.]])

>>> np.mean(x, axis=1)
array([[ 4., 5., 6., 7.],
[16., 17., 18., 19.]])

>>> x.mean(axis=2)
array([[ 1.5, 5.5, 9.5],
[13.5, 17.5, 21.5]])

16. sort 矩阵排序

>>> arr = np.random.random(8)*10
>>> arr
array([6.35321392, 7.47083843, 4.90362188, 5.10838496, 1.02263554,
6.29831149, 1.86713463, 3.64290343])

>>> arr.sort()
>>> arr
array([1.02263554, 1.86713463, 3.64290343, 4.90362188, 5.10838496,
6.29831149, 6.35321392, 7.47083843])

>>> arr = np.random.random((3, 5))*10
>>> arr
array([[7.38573723, 1.54610423, 8.1565099 , 9.74806757, 6.98749242],
[3.24464993, 9.95109972, 1.03708113, 4.5464522 , 9.4270873 ],
[1.78004297, 6.74287299, 6.02383947, 8.04662578, 6.53910146]])

>>> arr.sort(0)
>>> arr
array([[1.78004297, 1.54610423, 1.03708113, 4.5464522 , 6.53910146],
[3.24464993, 6.74287299, 6.02383947, 8.04662578, 6.98749242],
[7.38573723, 9.95109972, 8.1565099 , 9.74806757, 9.4270873 ]])

5. Broadcasting 广播

>>> x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
>>> v = np.array([1, 0, 1])
>>> x, v
(array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]]),
array([1, 0, 1]))

>>> y = np.empty_like(x)
>>> for i in range(4):
>>> y[i,:] = x[i,:] + v

>>> y
[[ 2 2 4]
[ 5 5 7]
[ 8 8 10]
[11 11 13]]

# 与上等效
>>> x + v
array([[ 2, 2, 4],
[ 5, 5, 7],
[ 8, 8, 10],
[11, 11, 13]])

当操作两个 array 时,numpy 会逐个比较它们的 shape,在下述情况下,两 arrays 会兼容和输出 broadcasting 结果:

A      (3d array): 256 x 256 x 3
B (1d array): 3
Result (3d array): 256 x 256 x 3

A (4d array): 8 x 1 x 6 x 1
B (3d array): 7 x 1 x 5
Result (4d array): 8 x 7 x 6 x 5

A (2d array): 5 x 4
B (1d array): 1
Result (2d array): 5 x 4

A (2d array): 15 x 3 x 5
B (1d array): 15 x 1 x 5
Result (2d array): 15 x 3 x 5
>>> v = np.array([1, 2, 3])
>>> w = np.array([4, 5])
>>> v = v.reshape(3, 1)
>>> v
array([[1],
[2],
[3]])

>>> v + w
array([[5, 6],
[6, 7],
[7, 8]])

>>> x = np.array([[1, 2, 3], [4, 5, 6]])
>>> v = np.array([1, 2, 3])
>>> x + v
array([[2, 4, 6],
[5, 7, 9]])

>>> x = np.array([[1, 2, 3], [4, 5, 6]]) # 2x3的
>>> w = np.array([4, 5]) # 2
>>> (x.T + w).T
array([[ 5, 6, 7],
[ 9, 10, 11]])

# 与上等效
>>> x + np.reshape(w, (2,1))
array([[ 5, 6, 7],
[ 9, 10, 11]])

Broadcasting 运算示意图

6. 逻辑运算

1. where

>>> x_arr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
>>> y_arr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
>>> cond = np.array([True, False, True, True, False])
# where 当前位为true时取第一个值,为false 时取第二个值
>>> print(np.where(cond, x_arr, y_arr))
[1.1 2.2 1.3 1.4 2.5]

>>> arr = np.random.randn(4, 4)
>>> arr
array([[ 0.22734657, 0.85939189, -0.53725899, -1.53371716],
[ 2.58570185, -0.4044316 , 0.96220121, 0.35446003],
[-1.37990352, 2.08273953, -1.42938058, 0.29720641],
[ 0.68013888, -0.25768069, 0.05425932, 1.36972457]])

>>> arr > 0
array([[ True, True, True, False],
[False, True, True, False],
[ True, False, True, True],
[ True, False, True, True]])

# where 自动将常数 1 和 -1 扩展成相应纬度的数组
>>> print(np.where(arr > 0, 1, -1))
[[ 1 1 1 -1]
[-1 1 1 -1]
[ 1 -1 1 1]
[ 1 -1 1 1]]

>>> print(np.where(arr > 0, 1, arr))
[[ 1. 1. 1. -1.1215865 ]
[-0.87007865 1. 1. -1.12037257]
[ 1. -0.69129334 1. 1. ]
[ 1. -0.39940992 1. 1. ]]

2. reshape

>>> arr = np.arange(8)
>>> arr.shape
(8,)

>>> arr.reshape(2, 4)
array([[0, 1, 2, 3],
[4, 5, 6, 7]])

>>> arr.reshape(2, 2, 2)
array([[[0, 1],
[2, 3]],

[[4, 5],
[6, 7]]])

>>> arr = np.arange(15)
>>> arr.reshape(5, 3).shape
(5, 3)

# 如果我们在某一个维度上写上-1,numpy会帮我们自动推导出正确的维度
>>> arr.reshape(5, -1).shape
(5, 3)

# 从其他的ndarray中获取shape信息然后reshape
>>> other_arr = np.ones((3, 5))
>>> arr.reshape(other_arr.shape)
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])

3. ravel 圧平

# 高维数组可以用ravel来拉平
>>> arr.ravel()
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

7. 二维数组拼接与裁剪

1. 连接数组

>>> arr1 = np.array([[1, 2, 3], [4, 5, 6]])
>>> arr2 = np.array([[7, 8, 9], [10, 11, 12]])
>>> print(arr1, "\n\n", arr2)
[[1 2 3]
[4 5 6]]

[[ 7 8 9]
[10 11 12]]

# axis = 0 表示第0维(行)
>>> np.concatenate([arr1, arr2], axis=0)
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]])

# axis = 1 表示第1维(列)
>>> np.concatenate([arr1, arr2], axis=1)
array([[ 1, 2, 3, 7, 8, 9],
[ 4, 5, 6, 10, 11, 12]])

# vertical
>>> np.vstack((arr1, arr2))
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]])

# horizontal
>>> np.hstack((arr1, arr2))
array([[ 1, 2, 3, 7, 8, 9],
[ 4, 5, 6, 10, 11, 12]])

2. 拆分数组

>>> arr = np.random.rand(5, 5)
# 从0维 1 和 3 的位置截断
>>> first, second, third = np.split(arr, [1, 3], axis=0)
>>> print(first, '\n\n', second, '\n\n', third)
[[0.3914401 0.50351343 0.73354434 0.99111918 0.10565332]]

[[0.8305255 0.17495142 0.80407256 0.21134664 0.8210997 ]
[0.40290273 0.10901759 0.02504847 0.66819861 0.64459658]]

[[0.76824859 0.39097992 0.21025703 0.18699943 0.91240376]
[0.854146 0.06411647 0.81970585 0.72851987 0.97605239]]

# 从1维 1 和 3 的位置截断
>>> first, second, third = np.split(arr, [1, 3], axis=1)
>>> print(first, '\n\n', second, '\n\n', third)
[[0.3914401 ]
[0.8305255 ]
[0.40290273]
[0.76824859]
[0.854146 ]]

[[0.50351343 0.73354434]
[0.17495142 0.80407256]
[0.10901759 0.02504847]
[0.39097992 0.21025703]
[0.06411647 0.81970585]]

[[0.99111918 0.10565332]
[0.21134664 0.8210997 ]
[0.66819861 0.64459658]
[0.18699943 0.91240376]
[0.72851987 0.97605239]]

3. 堆叠辅助

>>> arr = np.arange(6)
>>> arr1 = arr.reshape((3, 2))
>>> arr2 = np.random.randn(3, 2)
>>> print(arr1, '\n\n', arr2)
[[0 1]
[2 3]
[4 5]]

[[-0.00818406 0.31732695]
[-0.93238122 -0.72519933]
[-1.03642948 1.01568413]]

# r_用于按行堆叠
>>> arr_2 = np.r_[arr1, arr2]
>>> arr_2
array([[ 0. , 1. ],
[ 2. , 3. ],
[ 4. , 5. ],
[-0.00818406, 0.31732695],
[-0.93238122, -0.72519933],
[-1.03642948, 1.01568413]])

>>> arr = np.arange(6)
>>> arr = arr.reshape(6, 1)+arr
>>> arr1, arr2, arr3 = np.split(arr, [1, 3], axis=1)
>>> arr1, arr2, arr3
(array([[0],
[1],
[2],
[3],
[4],
[5]]),
array([[1, 2],
[2, 3],
[3, 4],
[4, 5],
[5, 6],
[6, 7]]),
array([[ 3, 4, 5],
[ 4, 5, 6],
[ 5, 6, 7],
[ 6, 7, 8],
[ 7, 8, 9],
[ 8, 9, 10]]))

# c_用于按列堆叠, 堆叠1维数组时可以自动转置
>>> np.c_[arr_2, arr1.reshape(6,)], np.c_[arr_2, arr2], np.c_[arr_2, arr3]
(array([[ 0. , 1. , 0. ],
[ 2. , 3. , 1. ],
[ 4. , 5. , 2. ],
[-0.00818406, 0.31732695, 3. ],
[-0.93238122, -0.72519933, 4. ],
[-1.03642948, 1.01568413, 5. ]]),
array([[ 0. , 1. , 1. , 2. ],
[ 2. , 3. , 2. , 3. ],
[ 4. , 5. , 3. , 4. ],
[-0.00818406, 0.31732695, 4. , 5. ],
[-0.93238122, -0.72519933, 5. , 6. ],
[-1.03642948, 1.01568413, 6. , 7. ]]),
array([[ 0.00000000e+00, 1.00000000e+00, 3.00000000e+00,
4.00000000e+00, 5.00000000e+00],
[ 2.00000000e+00, 3.00000000e+00, 4.00000000e+00,
5.00000000e+00, 6.00000000e+00],
[ 4.00000000e+00, 5.00000000e+00, 5.00000000e+00,
6.00000000e+00, 7.00000000e+00],
[-8.18406429e-03, 3.17326952e-01, 6.00000000e+00,
7.00000000e+00, 8.00000000e+00],
[-9.32381218e-01, -7.25199326e-01, 7.00000000e+00,
8.00000000e+00, 9.00000000e+00],
[-1.03642948e+00, 1.01568413e+00, 8.00000000e+00,
9.00000000e+00, 1.00000000e+01]]))

4. 切片转数组

# 切片直接转为数组
>>> np.c_[1:6, -5:0]
array([[ 1, -5],
[ 2, -4],
[ 3, -3],
[ 4, -2],
[ 5, -1]])

# 切片直接转为数组
>>> np.r_[np.r_[1:6].reshape(1, 5), np.r_[-5:0].reshape(1, 5)]
array([[ 1, 2, 3, 4, 5],
[-5, -4, -3, -2, -1]])

5. 行列重复

# 使用repeat来重复
>>> arr = np.arange(3)
>>> arr.repeat(3)
array([0, 0, 0, 1, 1, 1, 2, 2, 2])

# 每个元素指定重复次数
>>> arr.repeat([2, 3, 5])
array([0, 0, 1, 1, 1, 2, 2, 2, 2, 2])

# 指定axis来重复
>>> arr = np.random.rand(2, 2)
>>> arr.repeat(2, axis=0)
array([[0.03870754, 0.93205818],
[0.03870754, 0.93205818],
[0.21127485, 0.90167588],
[0.21127485, 0.90167588]])

>>> arr.repeat(2, axis=1)
array([[0.03870754, 0.03870754, 0.93205818, 0.93205818],
[0.21127485, 0.21127485, 0.90167588, 0.90167588]])

6. 整块重复

# Tile 整块重复
>>> print(arr)
[[0.03870754 0.93205818]
[0.21127485 0.90167588]]

>>> print(np.tile(arr, 2))
[[0.03870754 0.93205818 0.03870754 0.93205818]
[0.21127485 0.90167588 0.21127485 0.90167588]]

# (2, 3) 表示按行重复两遍,按列重复三遍
>>> print(np.tile(arr, (2, 3)))
[[0.03870754 0.93205818 0.03870754 0.93205818 0.03870754 0.93205818]
[0.21127485 0.90167588 0.21127485 0.90167588 0.21127485 0.90167588]
[0.03870754 0.93205818 0.03870754 0.93205818 0.03870754 0.93205818]
[0.21127485 0.90167588 0.21127485 0.90167588 0.21127485 0.90167588]]

8. 文件输入输出

1. 保存单个数组

# 读取csv文件作为数组
>>> arr = np.loadtxt('data/pf_gd.txt', delimiter=',')
>>> arr, arr.dtype
(array([[0.26338619, 0.26338619, 0.43161792, 0.43161792],
[0.22527752, 0.22527752, 0.41270022, 0.41270022]]),
dtype('float64'))

# 保存单个数组
>>> arr = np.arange(50).reshape(2, 5, 5)
>>> np.save('data/some_array', arr)

# 重新加载数组
>>> arr2 = np.load('data/some_array.npy')
>>> print(arr2)
[[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]

[[25 26 27 28 29]
[30 31 32 33 34]
[35 36 37 38 39]
[40 41 42 43 44]
[45 46 47 48 49]]]

2. 保存多个数组

# 保存多个数组
>>> arr3 = np.arange(15).reshape(3, 5)
>>> np.savez("data/array_archive.npz", arr=arr, b=arr2, c=arr3)

# 加载 npz 多数组
>>> arch = np.load('data/array_archive.npz')
>>> arch['arr']
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]],

[[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34],
[35, 36, 37, 38, 39],
[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49]]])

>>> arch['b']
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]],

[[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34],
[35, 36, 37, 38, 39],
[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49]]])

>>> arch['c']
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])

9. softmax 计算

>>> m = np.random.rand(10, 10) * 10 + 1000
>>> print(m)
[[1004.01509238 1003.95791041 1009.61573288 1002.71112709 1007.37791263
1002.92944407 1004.38080821 1008.93340429 1003.836364 1005.65500045]
[1007.44997195 1005.0208236 1009.88068172 1008.78507112 1009.11716663
1003.12627626 1008.42046111 1005.12853182 1003.77996436 1003.28019564]
[1000.07014115 1000.82257105 1008.97177068 1003.90030445 1004.69847582
1001.11815882 1008.9957145 1009.29890558 1009.88689132 1001.12402356]
[1009.14998806 1003.01260378 1001.98328372 1003.51481905 1001.18429502
1008.9694852 1005.86934584 1006.06563433 1004.19213641 1006.15450872]
[1008.76391228 1007.97595255 1004.53976701 1001.05601321 1007.69300121
1004.80470998 1003.73956324 1002.16719292 1001.73853401 1000.16201767]
[1005.27092332 1001.50002372 1009.05864521 1005.49681408 1002.09039322
1000.7459654 1000.55967764 1002.22267797 1002.60272384 1001.49422364]
[1003.77845077 1001.39280884 1003.50564572 1005.67295031 1006.14985866
1000.27695442 1006.1710507 1004.78522787 1009.6945348 1000.09435959]
[1007.82182287 1002.96531963 1003.30024203 1008.33030557 1002.51316723
1003.71405055 1000.47738557 1009.33441914 1008.33329613 1008.90991154]
[1008.79861011 1001.06733787 1003.1876972 1007.1979645 1008.83907927
1008.83525759 1003.60526858 1006.40745144 1005.33060026 1007.74591685]
[1004.9997751 1009.50142732 1000.13304765 1007.24933319 1007.78516144
1009.60037336 1000.23504095 1006.52181851 1003.56427857 1007.60400671]]

# 每行最大值
>>> m_row_max = m.max(axis=1).reshape(10, 1)
>>> print(m_row_max, m_row_max.shape)
[[1009.61573288]
[1009.88068172]
[1009.88689132]
[1009.14998806]
[1008.76391228]
[1009.05864521]
[1009.6945348 ]
[1009.33441914]
[1008.83907927]
[1009.60037336]] (10, 1)

>>> m = m - m_row_max
>>> print(m)
[[-5.60064050e+00 -5.65782246e+00 0.00000000e+00 -6.90460578e+00
-2.23782024e+00 -6.68628881e+00 -5.23492466e+00 -6.82328582e-01
-5.77936887e+00 -3.96073242e+00]
[-2.43070977e+00 -4.85985812e+00 0.00000000e+00 -1.09561059e+00
-7.63515088e-01 -6.75440545e+00 -1.46022061e+00 -4.75214990e+00
-6.10071736e+00 -6.60048608e+00]
[-9.81675016e+00 -9.06432027e+00 -9.15120642e-01 -5.98658687e+00
-5.18841550e+00 -8.76873250e+00 -8.91176817e-01 -5.87985736e-01
0.00000000e+00 -8.76286776e+00]
[ 0.00000000e+00 -6.13738428e+00 -7.16670434e+00 -5.63516901e+00
-7.96569304e+00 -1.80502866e-01 -3.28064222e+00 -3.08435373e+00
-4.95785165e+00 -2.99547935e+00]
[ 0.00000000e+00 -7.87959730e-01 -4.22414526e+00 -7.70789907e+00
-1.07091107e+00 -3.95920230e+00 -5.02434904e+00 -6.59671936e+00
-7.02537827e+00 -8.60189461e+00]
[-3.78772189e+00 -7.55862149e+00 0.00000000e+00 -3.56183113e+00
-6.96825200e+00 -8.31267981e+00 -8.49896757e+00 -6.83596724e+00
-6.45592138e+00 -7.56442157e+00]
[-5.91608403e+00 -8.30172596e+00 -6.18888908e+00 -4.02158449e+00
-3.54467614e+00 -9.41758038e+00 -3.52348410e+00 -4.90930693e+00
0.00000000e+00 -9.60017521e+00]
[-1.51259626e+00 -6.36909950e+00 -6.03417710e+00 -1.00411357e+00
-6.82125190e+00 -5.62036858e+00 -8.85703357e+00 0.00000000e+00
-1.00112301e+00 -4.24507591e-01]
[-4.04691602e-02 -7.77174140e+00 -5.65138207e+00 -1.64111477e+00
0.00000000e+00 -3.82168543e-03 -5.23381069e+00 -2.43162783e+00
-3.50847901e+00 -1.09316242e+00]
[-4.60059826e+00 -9.89460403e-02 -9.46732571e+00 -2.35104017e+00
-1.81521192e+00 0.00000000e+00 -9.36533241e+00 -3.07855485e+00
-6.03609479e+00 -1.99636665e+00]]

# e 的 m 次方
>>> m_exp = np.exp(m)
>>> print(m_exp, m_exp.shape)
[[3.69549601e-03 3.49010848e-03 1.00000000e+00 1.00315446e-03
1.06690811e-01 1.24790541e-03 5.32722581e-03 5.05438666e-01
3.09066539e-03 1.90491571e-02]
[8.79743690e-02 7.75158363e-03 1.00000000e+00 3.34335402e-01
4.66025424e-01 1.16573271e-03 2.32185047e-01 8.63311493e-03
2.24125936e-03 1.35970695e-03]
[5.45305117e-05 1.15721945e-04 4.00468310e-01 2.51222399e-03
5.58084264e-03 1.55520579e-04 4.10172770e-01 5.55444972e-01
1.00000000e+00 1.56435346e-04]
[1.00000000e+00 2.16056766e-03 7.71862342e-04 3.57007380e-03
3.47171022e-04 8.34850288e-01 3.76040991e-02 4.57595974e-02
7.02801023e-03 5.00126480e-02]
[1.00000000e+00 4.54771706e-01 1.46378409e-02 4.49264361e-04
3.42696156e-01 1.90783270e-02 6.57586571e-03 1.36483824e-03
8.89031162e-04 1.83757316e-04]
[2.26471358e-02 5.21593771e-04 1.00000000e+00 2.83867972e-02
9.41296859e-04 2.45385574e-04 2.03678544e-04 1.07442758e-03
1.57119096e-03 5.18577241e-04]
[2.69573596e-03 2.48088267e-04 2.05210521e-03 1.79245412e-02
2.88779734e-02 8.12824544e-05 2.94964874e-02 7.37759975e-03
1.00000000e+00 6.77168710e-05]
[2.20337182e-01 1.71370171e-03 2.39546694e-03 3.66369253e-01
1.09035505e-03 3.62330537e-03 1.42376790e-04 1.00000000e+00
3.67466543e-01 6.54091786e-01]
[9.60338781e-01 4.21478664e-04 3.51265866e-03 1.93763919e-01
1.00000000e+00 9.96185608e-01 5.33316350e-03 8.78936399e-02
2.99424220e-02 3.35154915e-01]
[1.00458239e-02 9.05791583e-01 7.73379551e-05 9.52700132e-02
1.62803404e-01 1.00000000e+00 8.56421993e-05 4.60257228e-02
2.39087758e-03 1.35827898e-01]] (10, 10)

>>> m_exp_row_sum = m_exp.sum(axis=1).reshape(10, 1)
>>> print(m_exp_row_sum, m_exp_row_sum.shape)
[[1.64903319]
[2.14167164]
[2.37466133]
[1.98210432]
[1.84064679]
[1.05611008]
[1.08882153]
[2.61722997]
[3.61254659]
[2.3583183 ]] (10, 1)

>>> m_softmax = m_exp / m_exp_row_sum
>>> print(m_softmax)
[[2.24100766e-03 2.11645739e-03 6.06415933e-01 6.08328850e-04
6.46990078e-02 7.56749721e-04 3.23051461e-03 3.06506060e-01
1.87422874e-03 1.15517124e-02]
[4.10774310e-02 3.61940808e-03 4.66924986e-01 1.56109553e-01
2.17598915e-01 5.44309729e-04 1.08413000e-01 4.03101707e-03
1.04649999e-03 6.34881149e-04]
[2.29634900e-05 4.87319784e-05 1.68642284e-01 1.05792938e-03
2.35016361e-03 6.54916880e-05 1.72728955e-01 2.33904922e-01
4.21112682e-01 6.58769083e-05]
[5.04514314e-01 1.09003731e-03 3.89415600e-04 1.80115333e-03
1.75152750e-04 4.21193920e-01 1.89718062e-02 2.30863719e-02
3.54573176e-03 2.52320968e-02]
[5.43287287e-01 2.47071687e-01 7.95255285e-03 2.44079616e-04
1.86182465e-01 1.03650125e-02 3.57258424e-03 7.41499266e-04
4.82999329e-04 9.98330135e-05]
[2.14439159e-02 4.93882010e-04 9.46870990e-01 2.68786347e-02
8.91286689e-04 2.32348481e-04 1.92857304e-04 1.01734431e-03
1.48771514e-03 4.91025745e-04]
[2.47582903e-03 2.27850259e-04 1.88470301e-03 1.64623317e-02
2.65222285e-02 7.46517700e-05 2.70902866e-02 6.77576586e-03
9.18424160e-01 6.21928104e-05]
[8.41871690e-02 6.54776896e-04 9.15268038e-04 1.39983592e-01
4.16606512e-04 1.38440466e-03 5.43998011e-05 3.82083352e-01
1.40402848e-01 2.49917582e-01]
[2.65834297e-01 1.16670790e-04 9.72349720e-04 5.36363793e-02
2.76813039e-01 2.75757166e-01 1.47628920e-03 2.43301056e-02
8.28845284e-03 9.27752508e-02]
[4.25974048e-03 3.84083685e-01 3.27936882e-05 4.03974362e-02
6.90336854e-02 4.24030971e-01 3.63149449e-05 1.95163319e-02
1.01380614e-03 5.75952354e-02]]

>>> print(m_softmax.sum(axis=1))
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]

PS:欢迎各路道友阅读评论,感谢道友点赞关注收藏