zoukankan      html  css  js  c++  java
  • Numpy学习笔记(下篇)

    Numpy学习笔记(下篇)


    路漫漫其修远兮,吾将上下而求索!Numpy学习笔记(上篇)

    一、Numpy数组的合并与分割操作

    ​ 在机器学习算法的使用中会经常使用这两种操作。

    1、合并操作

    import numpy as np
    x = np.array([1, 2, 3])
    y = np.array([3, 2, 1])
    z = np.array([666, 666, 666])
    
    • np.concatenate([,], axis=) 默认axis=0,拼接之后返回的是一个新的数组。不改变原有数组。
    np.concatenate([x, y])
    

    运行输出结果:array([1, 2, 3, 3, 2, 1])

    np.concatenate([x, y, z])
    

    运行输出结果:array([ 1, 2, 3, 3, 2, 1, 666, 666, 666])

    ​ 上面是对一维数组的拼接,接下来看看二维的。

    A = np.array([[1, 2, 3],
                 [4, 5, 6]])	# A.shape=(2,3),从第一个维度上拼接就是(4,3)
    np.concatenate([A, A])
    

    运行输出结果:

    array([[1, 2, 3],
           [4, 5, 6],
           [1, 2, 3],
           [4, 5, 6]])
    
    np.concatenate([A, A], axis=1)		# 从第二个维度上拼接就是(2,6)
    

    运行输出结果:

    array([[1, 2, 3, 1, 2, 3],
           [4, 5, 6, 4, 5, 6]])
    

    ​ 那么,能不能把A和z拼接到一起呢?显然是不能的,因为z是1维数组,而A是2维数组,运行会报错。z.shape=(3,),此时我们就可以使用reshape操作将其先装换为2维数组,然后再进行拼接。

    np.concatenate([A, z.reshape(1, -1)])
    

    运行输出结果:

    array([[  1,   2,   3],
           [  4,   5,   6],
           [666, 666, 666]])
    
    

    ​ 其实,在numpy中已经封装好了一个函数用来解决不同维度之间的合并问题。

    • np.vstack()
    np.vstack([A, z])
    
    

    运行输出结果:

    array([[  1,   2,   3],
           [  4,   5,   6],
           [666, 666, 666]])
    
    
    • np.hstack()
    B = np.full((2, 2), 100)
    np.hstack([A, B])
    
    
    array([[  1,   2,   3, 100, 100],
           [  4,   5,   6, 100, 100]])
    
    

    2、分割操作

    • np.split(x, [,], axis=)

      第一个参数是分割对象,第二个参数是分割点,且分割点可以不唯一。axis默认是0

    x = np.arange(10)
    x
    
    

    运行输出结果:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

    np.split(x, [3, 7])
    
    

    运行输出结果:[array([0, 1, 2]), array([3, 4, 5, 6]), array([7, 8, 9])]

    ​ 同样的,接下来试一下二维数组。

    A = np.arange(16).reshape(4, 4)
    A
    
    

    运行输出结果:

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

    运行输出结果:

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

    运行输出结果:

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

    ​ 其实,在numpy中既然有垂直水平拼接,那就有垂直水平分割。

    • np.vsplit()
    np.vsplit(A, [3])
    
    

    运行输出结果:

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

    运行输出结果:

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

    ​ 通过以上对比可以发现:其实vsplit就是split的axis=0的时候,而hsplit就是split的axis=1的时候!

    ​ 那么接下来做一个简答的小练习,现在有下面一组数据,前三列为数据,最后一列为样本标签,此时我们需要将其分割开来,同时把标签(最后一列)转换为向量:

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

    data = np.arange(16).reshape(4, 4)
    x, y = np.hsplit(data, [-1])
    
    

    运行输出结果:

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

    ​ 接下来需要把array转换为向量。

    y[:, 0]
    
    

    运行输出结果:array([ 3, 7, 11, 15])

    二、Numpy中的矩阵运算

    ​ 现在有这么一个问题:给定一个向量,让向量中的每一个元素乘以2,a=(0,1,2),a*2=(0,2,4)

    L = [i for i in range(10)]
    L * 2
    
    

    运行输出结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    ​ 显然这不是我们想要的结果。那么想要实现怎么办呢?

    A = []
    for i in L:
        A.append(i * 2)
    A
    
    

    运行输出结果:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

    ​ 这肯定不是最优的办法,下面就来对比几种实现方式的快慢。

    %%time
    L = [i for i in range(100000)]
    A = []
    for i in L:
        A.append(i * 2)
    A
    
    

    运行输出结果:Wall time: 14.6 ms

    %%time
    L = [i*2 for i in range(100000)]
    
    

    运行输出结果:Wall time: 6.83 ms

    %%time
    import numpy as np
    A = np.array(i*2 for i in range(100000000000000))
    A
    
    
    %%time
    L = np.arange(10)
    L * 2
    L
    
    

    运行输出结果:Wall time: 0 ns

    ​ 为什么是0呢?其实因为A返回的是一个生成器,无论后面有多大的的数都是一样的。这就是numpy在大数据运算中的优势所在。关于生成器

    import numpy as np
    L = np.arange(10)
    L * 2
    
    

    运行输出结果:array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])

    1、Universal Function

    X = np.arange(1, 16).reshape(3, 5)
    X
    
    

    运行输出结果:

    array([[ 1,  2,  3,  4,  5],
           [ 6,  7,  8,  9, 10],
           [11, 12, 13, 14, 15]])
    
    
    • 加法
    X + 1
    
    

    运行输出结果:

    array([[ 2,  3,  4,  5,  6],
           [ 7,  8,  9, 10, 11],
           [12, 13, 14, 15, 16]])
    
    
    • 减法
    array([[ 0,  1,  2,  3,  4],
           [ 5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14]])
    
    
    • 乘法
    X * 2
    
    

    运行输出结果:

    array([[ 2,  4,  6,  8, 10],
           [12, 14, 16, 18, 20],
           [22, 24, 26, 28, 30]])
    
    
    • 除法
    X / 2
    
    

    运行输出结果:

    array([[0.5, 1. , 1.5, 2. , 2.5],
           [3. , 3.5, 4. , 4.5, 5. ],
           [5.5, 6. , 6.5, 7. , 7.5]])
    
    
    X // 2
    
    

    运行输出结果:

    array([[0, 1, 1, 2, 2],
           [3, 3, 4, 4, 5],
           [5, 6, 6, 7, 7]], dtype=int32)
    
    
    • 取余
    X % 2
    
    

    运行输出结果:

    array([[1, 0, 1, 0, 1],
           [0, 1, 0, 1, 0],
           [1, 0, 1, 0, 1]], dtype=int32)
    
    
    • 倒数——1/X
    • 绝对值——np.abs()
    • 正弦函数——np.sin()
    • 余弦函数——np.cos()
    • 正切函数——np.tan()
    • 同样还有反正弦、反余弦、反正切等等。
    • 指数函数——np.exp()
    • np.power()
    • np.log()
    • np.log2()
    • np.log10()

    2、矩阵运算

    A = np.arange(4).reshape(2, 2)
    B = np.full((2, 2), 10)
    
    
    • A+B

    • A-B

    • A*B

    • A/B

      ​ 以上方法都是对应元素进行相应操作,那么如果需要进行矩阵乘法怎么办?

    • 矩阵乘法——np.dot()

    A.dot(B)
    
    

    运行输出结果:

    array([[10, 10],
           [50, 50]])
    
    
    • 矩阵转置
    A.T
    
    

    运行输出结果:

    array([[0, 2],
           [1, 3]])
    
    
    • 矩阵的逆——np.linalg.inv()
    np.linalg.inv(A)
    
    

    运行输出结果:

    array([[-1.5,  0.5],
           [ 1. ,  0. ]])
    
    
    np.linalg.inv(A).dot(A)
    
    

    运行输出结果:

    array([[1., 0.],
           [0., 1.]])
    
    

    ​ 这也验证了A*A[^-1]=E

    • 矩阵的伪逆——np.linalg.pinv()

      很多情况下,我们的矩阵可能不是一个方阵,那么此时正常情况下我们是无法求得矩阵的逆的。但是可以求得伪逆矩阵。

    C = np.arange(0, 16).reshape(2, 8)
    C = np.arange(0, 16).reshape(2, 8)
    
    

    运行输出结果:

    array([[-1.35416667e-01,  5.20833333e-02],
           [-1.01190476e-01,  4.16666667e-02],
           [-6.69642857e-02,  3.12500000e-02],
           [-3.27380952e-02,  2.08333333e-02],
           [ 1.48809524e-03,  1.04166667e-02],
           [ 3.57142857e-02, -1.04083409e-17],
           [ 6.99404762e-02, -1.04166667e-02],
           [ 1.04166667e-01, -2.08333333e-02]])
    
    
    C.dot(np.linalg.pinv(C))
    
    

    运行输出结果:

    array([[ 1.00000000e+00, -2.49800181e-16],
           [ 0.00000000e+00,  1.00000000e+00]])
    
    

    ​ 通过上述结果可以发现,近似单位矩阵说明求得是伪逆矩阵,近似得到的。具体伪逆矩阵的详细求解自行百度!

    3、向量和矩阵运算

    A = np.arange(4).reshape(2, 2)
    v = np.array([1, 2])
    
    
    • v+A
    v + A
    
    

    运行输出结果:

    array([[1, 3],
           [3, 5]])
    
    
    np.vstack([v] * A.shape[0])
    
    

    运行输出结果:

    array([[1, 2],
           [1, 2]])
    
    
    np.vstack([v] * A.shape[0]) + A
    
    

    运行输出结果:

    array([[1, 3],
           [3, 5]])
    
    

    ​ 此时,可以发现两者得到的结果是相同的。其实在pyhon中已经封装了堆叠的函数

    • np.tile()
    np.tile(v, (2, 1))
    
    

    运行输出结果:

    array([[1, 2],
           [1, 2]])
    
    
    np.tile(v, (2, 1)) + A
    
    

    运行输出结果:

    array([[1, 3],
           [3, 5]])
    
    
    • v *A
    v * A
    
    

    运行输出结果:

    array([[0, 2],
           [2, 6]])
    
    
    • A.dot(v)
    A.dot(v)
    
    

    运行输出结果:array([2, 8])

    • v.dot(A)
    v.dot(A)
    
    

    运行输出结果:array([4, 7])

    三、Numpy中的聚合操作

    import numpy as np
    L = np.random.random(100)
    
    

    运行输出结果:

    array([0.21395159, 0.90268106, 0.88705369, 0.11517909, 0.62676208,
           0.56121013, 0.62103571, 0.2418181 , 0.13781453, 0.66670862,
           0.51939238, 0.99679432, 0.06384017, 0.5974129 , 0.22196488,
           0.93826983, 0.83706847, 0.63491905, 0.48828241, 0.85424059,
           0.86514318, 0.47937265, 0.34254143, 0.89577197, 0.14823176,
           0.94488872, 0.57030248, 0.57643624, 0.08268558, 0.8237711 ,
           0.21887705, 0.46440547, 0.9338367 , 0.132422  , 0.4867988 ,
           0.6545799 , 0.36226663, 0.01641314, 0.67876507, 0.35811434,
           0.36533195, 0.12174504, 0.37477359, 0.98791281, 0.20553232,
           0.65235494, 0.13567244, 0.92317556, 0.82237976, 0.62747037,
           0.41160535, 0.46839494, 0.06753446, 0.22386476, 0.20821765,
           0.11778734, 0.8643039 , 0.77497708, 0.9884161 , 0.65142779,
           0.2374325 , 0.32467954, 0.81959546, 0.9863651 , 0.54072234,
           0.21293241, 0.92733881, 0.98738362, 0.90565471, 0.23441948,
           0.05477787, 0.69157053, 0.49194796, 0.12415383, 0.55427813,
           0.29040539, 0.20166942, 0.30054924, 0.30772375, 0.90932004,
           0.84668024, 0.51970052, 0.67773186, 0.37401172, 0.43911304,
           0.98495573, 0.42493635, 0.83658015, 0.35920119, 0.91977698,
           0.95094167, 0.03354397, 0.92045222, 0.80083071, 0.03480189,
           0.22378161, 0.21437509, 0.33268728, 0.51601075, 0.61235958])
    
    
    • 求和——np.sum()
    sum(L)
    
    

    运行输出结果:52.28029464862967

    np.sum(L)
    
    

    运行输出结果:52.28029464862967

    ​ 那么这两者有什么不一样呢?其实就是单纯的效率上不一样。

    • 最小值——np.min()
    np.min(L)
    
    

    运行输出结果:0.016413139615859218

    • 最大值——np.max()
    np.max(L)
    
    

    运行输出结果:0.9967943174823842

    ​ 接下来,试一下二维数组。

    X = np.arange(16).reshape(4, -1)
    X
    
    

    运行输出结果:

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

    运行输出结果:120

    ​ 但是,很多时候我们并不是需要将所有的数进行求和,而是只需要求每一行或者每一列的和。

    np.sum(X, axis=0)
    
    

    运行输出结果:array([24, 28, 32, 36])

    np.sum(X, axis=1)
    
    

    运行输出结果:array([ 6, 22, 38, 54])

    ​ 在这里,放一个小技巧,axis=0其实就是要把行压缩掉,那就是说不管有多少行直接压缩为一行,那也就是将每一行放在一起求和,axis=1其实就是把列压缩掉,最终的结果就是每一行出一个数。因为按行求和和按列求和记起来其实并不是那么方便。

    • 累乘——np.prod()
    np.prod(X)
    
    

    运行输出结果:0

    np.prod(X + 1)
    
    

    运行输出结果:2004189184

    • 均值——np.mean()
    np.mean(X)
    
    

    运行输出结果:7.5

    • 中位数——np.median()
    np.median(X)
    
    

    运行输出结果:7.5

    • 百分位——np.precentile()
    X = np.arange(16).reshape(4, -1)
    for percent in [0, 25, 50, 75, 100]:
        print(np.percentile(X, q=percent))
    
    

    运行输出结果:

    0.0
    3.75
    7.5
    11.25
    15.0
    
    
    • 方差——np.var()
    np.var(X)
    
    

    运行输出结果:21.25

    • 标准差——np.std()
    np.std(X)
    
    

    运行输出结果:4.6097722286464435

    四、Numpy中的arg运算

    1、索引操作

    • np.argmin() # 最小值所在位置的索引
    • np.argmax() # 最大值所在位置的索引

    2、排序和索引使用

    # 首先生成一个乱序数组
    import numpy as np
    x = np.arange(16)
    np.random.shuffle(x)
    x
    
    

    运行输出结果:array([ 4, 2, 8, 14, 0, 15, 6, 3, 11, 7, 13, 1, 12, 10, 9, 5])

    • np.sort(x, axis=) 默认axis=1
    np.sort(x)
    
    

    运行输出结果:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])

    ​ 此时,并没有改变x,x仍是一个乱序的状态,如果想要直接在x上进行排序:

    x.sort()
    x
    
    

    运行输出结果:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])

    ​ 那么对于二维矩阵呢?

    X = np.random.randint(10, size=(4, 4))
    X
    
    

    运行输出结果:

    array([[5, 3, 9, 2],
           [3, 7, 5, 7],
           [0, 6, 2, 0],
           [8, 7, 4, 8]])
    
    
    np.sort(X, axis=0)
    
    

    运行输出结果:

    array([[0, 3, 2, 0],
           [3, 6, 4, 2],
           [5, 7, 5, 7],
           [8, 7, 9, 8]])
    
    
    • np.argsort() 按照索引位置排序
    import numpy as np
    x = np.arange(16)
    np.random.shuffle(x)
    
    
    np.argsort(x)
    
    

    运行输出结果:

    array([ 1, 15,  9,  0, 10,  8, 12, 13,  5,  4,  6,  2,  3, 14, 11,  7],
          dtype=int64)
    
    
    • np.partition()

      其实,在很多情况下,我们并不需要将所有数进行从大到小排序,而是寻找一个中间值,小于中间值的在左边,大于中间值的在右边。

    np.partition(x, 3)
    
    

    运行输出结果: array([ 0, 1, 2, 3, 9, 8, 10, 12, 5, 11, 4, 14, 6, 7, 13, 15])

    • np.argpartition()
    np.argpartition(x, 3)
    
    

    运行输出结果:

    array([ 1, 15,  9,  0,  4,  5,  6,  3,  8,  2, 10, 11, 12, 13, 14,  7],
          dtype=int64)
    
    

    五、Fancy Indexing

    import numpy as np
    x = np.arange(16)
    
    

    ​ 如果我们需要从3-9每间隔2个取一个数?

    x[3:9:2]
    
    

    运行输出结果: array([3, 5, 7])

    ​ 如果我们需要去取得数据不是等间距的呢?

    idx = [3, 5, 8]
    x[idx]
    
    

    运行输出结果:array([3, 5, 8])

    ind = np.array([[2, 3],
                   [4, 5]])
    x[ind]
    
    

    运行输出结果:

    array([[2, 3],
           [4, 5]])
    
    
    X = x.reshape(4, -1)
    row = np.array([0, 1, 2])
    col = np.array([1, 2, 3])
    X[row, col]
    
    

    运行输出结果:array([ 1, 6, 11])

    col = [True, False, True, True]
    X[1:3, col]
    
    

    运行输出结果:

    array([[ 4,  6,  7],
           [ 8, 10, 11]])
    
    

    六、Numpy.array的比较

    import numpy as np
    x = np.arange(16)
    x > 3
    
    

    运行输出结果:

    array([False, False, False, False,  True,  True,  True,  True,  True,
            True,  True,  True,  True,  True,  True,  True])
    
    
    • '>'

    • '<'

    • '>='

    • '<='

    • '=='

    • '!='

      ​ 结合刚刚学过的聚合操作,进行一些练习。

    np.sum(x <= 3)
    
    

    运行输出结果:4

    np.sum((x >= 3) & (x <= 10))
    
    

    运行输出结果:8

    np.count_nonzero(x <= 3)		# True为1,False为0
    
    

    运行输出结果:4

    • np.any()
    • np.all()
    • 与——&
    • 或——|
    • 非——~

    我是尾巴

    ​ 每篇一句毒鸡汤:千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。

    我干了,你随意!

    本次推荐:一款图片阅读器,预览更轻松

    honeyview

    坚持!

  • 相关阅读:
    Maven 环境的配置
    zTree的简单例子
    plsql免安装客户端的配置
    HDU 1232 畅通工程
    HDU 5698 瞬间移动
    Codeforces 1015E1 Stars Drawing (Easy Edition)
    Codeforces 784B Santa Claus and Keyboard Check
    Codeforces 500C New Year Book Reading
    NSarray 赋值 拷贝 等问题记录
    UINavigationController 操作记录
  • 原文地址:https://www.cnblogs.com/zhangkanghui/p/11280845.html
Copyright © 2011-2022 走看看