「Python 机器学习」Numpy 矩阵运算

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:欢迎各路道友阅读评论,感谢道友点赞关注收藏

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aurelius-Shu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值