📜  Python中的 NumPy |第 2 组(高级)

📅  最后修改于: 2022-05-13 01:55:21.909000             🧑  作者: Mango

Python中的 NumPy |第 2 组(高级)

Python中的 NumPy |第 1 套(介绍)

本文讨论了 NumPy 中可用的一些更高级的方法。

  1. 堆叠:几个阵列可以沿不同的轴堆叠在一起。
    • np.vstack:沿垂直轴堆叠数组。
    • np.hstack:沿水平轴堆叠数组。
    • np.column_stack:将一维数组作为列堆叠成二维数组。
    • np.concatenate:沿指定轴堆叠数组(轴作为参数传递)。
    import numpy as np
      
    a = np.array([[1, 2],
                  [3, 4]])
      
    b = np.array([[5, 6],
                  [7, 8]])
      
    # vertical stacking
    print("Vertical stacking:\n", np.vstack((a, b)))
      
    # horizontal stacking
    print("\nHorizontal stacking:\n", np.hstack((a, b)))
      
    c = [5, 6]
      
    # stacking columns
    print("\nColumn stacking:\n", np.column_stack((a, c)))
      
    # concatenation method 
    print("\nConcatenating to 2nd axis:\n", np.concatenate((a, b), 1))
    

    输出:

    Vertical stacking:
     [[1 2]
     [3 4]
     [5 6]
     [7 8]]
    
    Horizontal stacking:
     [[1 2 5 6]
     [3 4 7 8]]
    
    Column stacking:
     [[1 2 5]
     [3 4 6]]
    
    Concatenating to 2nd axis:
     [[1 2 5 6]
     [3 4 7 8]]
  2. 拆分:对于拆分,我们有以下功能:
    • np.hsplit:沿水平轴拆分数组。
    • np.vsplit:沿垂直轴拆分数组。
    • np.array_split:沿指定轴拆分数组。
    import numpy as np
      
    a = np.array([[1, 3, 5, 7, 9, 11],
                  [2, 4, 6, 8, 10, 12]])
      
    # horizontal splitting
    print("Splitting along horizontal axis into 2 parts:\n", np.hsplit(a, 2))
      
    # vertical splitting
    print("\nSplitting along vertical axis into 2 parts:\n", np.vsplit(a, 2))
    

    输出:

    Splitting along horizontal axis into 2 parts:
     [array([[1, 3, 5],
           [2, 4, 6]]), array([[ 7,  9, 11],
           [ 8, 10, 12]])]
    
    Splitting along vertical axis into 2 parts:
     [array([[ 1,  3,  5,  7,  9, 11]]), array([[ 2,  4,  6,  8, 10, 12]])]
  3. 广播:术语广播描述了 NumPy 在算术运算期间如何处理具有不同形状的数组。受限于某些限制,较小的阵列在较大的阵列上“广播”,以便它们具有兼容的形状。

    广播提供了一种向量化数组操作的方法,以便循环发生在 C 而不是Python中。它在不制作不必要的数据副本的情况下做到这一点,并且通常会导致有效的算法实现。在某些情况下,广播不是一个好主意,因为它会导致内存使用效率低下,从而减慢计算速度。

    NumPy 操作通常是逐个元素完成的,这需要两个数组具有完全相同的形状。当数组的形状满足某些约束时,Numpy 的广播规则会放宽此约束。

    广播规则:为了广播,一个操作中两个数组的尾轴大小必须相同,或者其中一个必须是1

    让我们看一些例子:

    A(2-D array): 4 x 3
    B(1-D array):     3
    Result      : 4 x 3
    
    A(4-D array): 7 x 1 x 6 x 1
    B(3-D array):     3 x 1 x 5
    Result      : 7 x 3 x 6 x 5
    

    但这将是不匹配的:

    A: 4 x 3
    B:     4
    

    最简单的广播示例发生在数组和标量值在操作中组合时。
    考虑下面给出的示例:

    import numpy as np
      
    a = np.array([1.0, 2.0, 3.0])
      
    # Example 1
    b = 2.0
    print(a * b)
      
    # Example 2
    c = [2.0, 2.0, 2.0]
    print(a * c)
    

    输出:

    [ 2.  4.  6.]
    [ 2.  4.  6.]

    我们可以认为标量 b 在算术运算期间被拉伸成一个与 a 形状相同的数组。如上图所示,b 中的新元素只是原始标量的副本。虽然,拉伸类比只是概念性的。
    Numpy 足够聪明,可以使用原始标量值而无需实际复制,因此广播操作尽可能地占用内存和计算效率。因为示例 1 在乘法过程中移动的内存更少(b 是一个标量,而不是数组),所以它比示例 2 在 Windows 2000 上使用标准 numpy 具有 100 万个元素数组快 10%!
    下图让概念更清晰:

    在上面的示例中,标量 b 被拉伸为与 a 具有相同形状的数组,因此这些形状与逐个元素的乘法兼容。

    现在,让我们看一个两个数组都被拉伸的例子。

    import numpy as np
      
    a = np.array([0.0, 10.0, 20.0, 30.0])
    b = np.array([0.0, 1.0, 2.0])
      
    print(a[:, np.newaxis] + b)
    

    输出:

    [[  0.   1.   2.]
     [ 10.  11.  12.]
     [ 20.  21.  22.]
     [ 30.  31.  32.]]
    

    1
    在某些情况下,广播会拉伸两个数组以形成一个大于任何一个初始数组的输出数组。

  4. 使用日期时间: Numpy 具有原生支持日期时间功能的核心数组数据类型。数据类型称为“datetime64”,之所以如此命名,是因为“datetime”已被Python中包含的 datetime 库采用。
    请考虑以下示例以获取一些示例:
    import numpy as np
      
    # creating a date
    today = np.datetime64('2017-02-12')
    print("Date is:", today)
    print("Year is:", np.datetime64(today, 'Y'))
      
    # creating array of dates in a month
    dates = np.arange('2017-02', '2017-03', dtype='datetime64[D]')
    print("\nDates of February, 2017:\n", dates)
    print("Today is February:", today in dates)
      
    # arithmetic operation on dates
    dur = np.datetime64('2017-05-22') - np.datetime64('2016-05-22')
    print("\nNo. of days:", dur)
    print("No. of weeks:", np.timedelta64(dur, 'W'))
      
    # sorting dates
    a = np.array(['2017-02-12', '2016-10-13', '2019-05-22'], dtype='datetime64')
    print("\nDates in sorted order:", np.sort(a))
    

    输出:

    Date is: 2017-02-12
    Year is: 2017
    
    Dates of February, 2017:
     ['2017-02-01' '2017-02-02' '2017-02-03' '2017-02-04' '2017-02-05'
     '2017-02-06' '2017-02-07' '2017-02-08' '2017-02-09' '2017-02-10'
     '2017-02-11' '2017-02-12' '2017-02-13' '2017-02-14' '2017-02-15'
     '2017-02-16' '2017-02-17' '2017-02-18' '2017-02-19' '2017-02-20'
     '2017-02-21' '2017-02-22' '2017-02-23' '2017-02-24' '2017-02-25'
     '2017-02-26' '2017-02-27' '2017-02-28']
    Today is February: True
    
    No. of days: 365 days
    No. of weeks: 52 weeks
    
    Dates in sorted order: ['2016-10-13' '2017-02-12' '2019-05-22']
  5. NumPy 中的线性代数:NumPy的线性代数模块提供了多种方法来在任何 numpy 数组上应用线性代数。
    你可以找到:
    • 数组的秩、行列式、跟踪等。
    • 矩阵的特征值
    • 矩阵和向量积(点积、内积、外积等)、矩阵求幂
    • 求解线性或张量方程等等!

    考虑下面的例子,它解释了我们如何使用 NumPy 来做一些矩阵运算。

    import numpy as np
      
    A = np.array([[6, 1, 1],
                  [4, -2, 5],
                  [2, 8, 7]])
      
    print("Rank of A:", np.linalg.matrix_rank(A))
      
    print("\nTrace of A:", np.trace(A))
      
    print("\nDeterminant of A:", np.linalg.det(A))
      
    print("\nInverse of A:\n", np.linalg.inv(A))
      
    print("\nMatrix A raised to power 3:\n", np.linalg.matrix_power(A, 3))
    

    输出:

    Rank of A: 3
    
    Trace of A: 11
    
    Determinant of A: -306.0
    
    Inverse of A:
     [[ 0.17647059 -0.00326797 -0.02287582]
     [ 0.05882353 -0.13071895  0.08496732]
     [-0.11764706  0.1503268   0.05228758]]
    
    Matrix A raised to power 3:
     [[336 162 228]
     [406 162 469]
     [698 702 905]]

    让我们假设我们要求解这个线性方程组:

    x + 2*y = 8
    3*x + 4*y = 18
    

    这个问题可以使用linalg.solve方法解决,如下例所示:

    import numpy as np
      
    # coefficients
    a = np.array([[1, 2], [3, 4]])
    # constants
    b = np.array([8, 18])
      
    print("Solution of linear equations:", np.linalg.solve(a, b))
    

    输出:

    Solution of linear equations: [ 2.  3.]

    最后,我们看到一个示例,该示例显示了如何使用最小二乘法执行线性回归。

    线性回归线的形式为 w1 x + w 2 = y,它是使每个数据点到该线的距离的平方和最小化的线。因此,给定 n 对数据 (xi, yi),我们正在寻找的参数是 w1 和 w2,它们使误差最小化:

    Numpy线性回归

    让我们看看下面的例子:

    import numpy as np
    import matplotlib.pyplot as plt
      
    # x co-ordinates
    x = np.arange(0, 9)
    A = np.array([x, np.ones(9)])
      
    # linearly generated sequence
    y = [19, 20, 20.5, 21.5, 22, 23, 23, 25.5, 24]
    # obtaining the parameters of regression line
    w = np.linalg.lstsq(A.T, y)[0] 
      
    # plotting the line
    line = w[0]*x + w[1] # regression line
    plt.plot(x, line, 'r-')
    plt.plot(x, y, 'o')
    plt.show()
    

    输出:

    4

因此,这导致了本系列 NumPy 教程的结束。

NumPy 是一个广泛使用的通用库,它是许多其他计算库(如 scipy、scikit-learn、tensorflow、matplotlib、opencv 等)的核心。对 NumPy 有基本的了解有助于有效地处理其他更高级别的库!

参考:

  • http://scipy.github.io/old-wiki/pages/EricsBroadcastingDoc
  • https://docs.scipy.org/doc/numpy/reference/arrays.datetime.html#arrays-dtypes-dateunits
  • https://docs.scipy.org/doc/numpy/reference/routines.linalg.html
  • http://glowingpython.blogspot.in/2012/03/linear-regression-with-numpy.html