Python中的 NumPy |第 2 组(高级)
Python中的 NumPy |第 1 套(介绍)
本文讨论了 NumPy 中可用的一些更高级的方法。
- 堆叠:几个阵列可以沿不同的轴堆叠在一起。
- 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]]
- 拆分:对于拆分,我们有以下功能:
- 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]])]
- 广播:术语广播描述了 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.]]
在某些情况下,广播会拉伸两个数组以形成一个大于任何一个初始数组的输出数组。 - 使用日期时间: 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']
- 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,它们使误差最小化:
让我们看看下面的例子:
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()
输出:
因此,这导致了本系列 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