背景這段時(shí)間,LSGO軟件技術(shù)團(tuán)隊(duì)正在組織 “機(jī)器學(xué)習(xí)實(shí)戰(zhàn)刻意練習(xí)”活動(dòng),,這個(gè)活動(dòng)是“Python基礎(chǔ)刻意練習(xí)”活動(dòng)的升級(jí),,是對(duì)學(xué)員們技術(shù)的更深層次的打磨。在用 Python 寫(xiě)各類機(jī)器學(xué)習(xí)算法時(shí),,我們經(jīng)常會(huì)用到 NumPy庫(kù),,故在這里總結(jié)一下,以方便學(xué)員們的學(xué)習(xí)。 什么是 NumPy 呢? NumPy 這個(gè)詞來(lái)源于兩個(gè)單詞 -- Numerical 和Python 。其是一個(gè)功能強(qiáng)大的 Python 庫(kù),可以幫助程序員輕松地進(jìn)行數(shù)值計(jì)算,通常應(yīng)用于以下場(chǎng)景: 執(zhí)行各種數(shù)學(xué)任務(wù),,如:數(shù)值積分、微分,、內(nèi)插,、外推等,。因此,,當(dāng)涉及到數(shù)學(xué)任務(wù)時(shí),它形成了一種基于 Python 的 MATLAB 的快速替代,。 計(jì)算機(jī)中的圖像表示為多維數(shù)字?jǐn)?shù)組,。NumPy 提供了一些優(yōu)秀的庫(kù)函數(shù)來(lái)快速處理圖像,。例如,鏡像圖像,、按特定角度旋轉(zhuǎn)圖像等,。 在編寫(xiě)機(jī)器學(xué)習(xí)算法時(shí),需要對(duì)矩陣進(jìn)行各種數(shù)值計(jì)算,。如:矩陣乘法,、求逆、換位,、加法等,。NumPy 數(shù)組用于存儲(chǔ)訓(xùn)練數(shù)據(jù)和機(jī)器學(xué)習(xí)模型的參數(shù),。
NumPy 基礎(chǔ)語(yǔ)法1. NumPy 中的數(shù)組 NumPy 提供的最重要的數(shù)據(jù)結(jié)構(gòu)是一個(gè)稱為 NumPy數(shù)組 的強(qiáng)大對(duì)象,。NumPy數(shù)組 是通常的 Python 列表的擴(kuò)展,。 1.1 創(chuàng)建一個(gè)數(shù)組 import numpy as np
# 1D Array a = np.array([0, 1, 2, 3, 4]) b = np.array((0, 1, 2, 3, 4)) c = np.arange(5) d = np.linspace(0, 2 * np.pi, 5)
print(a) # [0 1 2 3 4] print(b) # [0 1 2 3 4] print(c) # [0 1 2 3 4] print(d) # [0. 1.57079633 3.14159265 4.71238898 6.28318531] print(a[3]) # 3
array(object[, dtype, copy, order, subok, ndmin]) 從現(xiàn)有的數(shù)據(jù)創(chuàng)建一個(gè)數(shù)組。arange([start,] stop[, step,][, dtype]) 返回給定間隔內(nèi)的均勻間隔的值,。
linspace(start, stop[, num, endpoint, …]) 返回指定間隔內(nèi)的等間隔數(shù)字,。
上面的代碼顯示了創(chuàng)建數(shù)組的 4 種不同方法。最基本的方法是將序列傳遞給 NumPy 的array() 函數(shù),;你可以傳遞任何序列,,而不僅僅是常見(jiàn)的列表(list)數(shù)據(jù)類型。對(duì)數(shù)組進(jìn)行索引就像列表或任何其他 Python 序列一樣,。你也可以對(duì)它們進(jìn)行切片,。 上面的數(shù)組示例是如何使用 NumPy 表示向量的,接下來(lái)我們將看看如何使用多維數(shù)組表示矩陣和更多的信息,。 import numpy as np
# MD Array, a = np.array([[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]])
print(a[2, 4]) # 25
NumPy 提供了創(chuàng)建 Zero矩陣 的方法,。 zeros(shape[, dtype, order]) 返回給定形狀和類型的新數(shù)組,并用零填充,。
import numpy as np
a = np.zeros(5) b = np.zeros([2, 3]) print(a) # [0. 0. 0. 0. 0.] print(b) ''' [[0. 0. 0.] [0. 0. 0.]] '''
NumPy 提供了創(chuàng)建 One矩陣 的方法,。 ones(shape[, dtype, order]) 返回給定形狀和類型的新數(shù)組,并填充為1,。
import numpy as np
a = np.ones(5) b = np.ones([2, 3]) print(a) # [1. 1. 1. 1. 1.] print(b) ''' [[1. 1. 1.] [1. 1. 1.]] '''
NumPy 提供了創(chuàng)建 Random矩陣 的方法,。 import numpy as np
a = np.random.random(5) b = np.random.random([2, 3]) print(a) # [0.94855794 0.32057893 0.47848178 0.1779337 0.86017829] print(b) ''' [[0.76592562 0.71543738 0.58269856] [0.74960683 0.07028875 0.18083749]] '''
NumPy 提供了創(chuàng)建 Eye矩陣 的方法。 eye(N[, M, k, dtype, order]) 返回一個(gè)二維數(shù)組,,對(duì)角線上有一個(gè),,其他地方為零。
import numpy as np
a = np.eye(4) b = np.eye(2, 3) print(a) ''' [[ 1. 0. 0. 0.] [ 0. 1. 0. 0.] [ 0. 0. 1. 0.] [ 0. 0. 0. 1.]] ''' print(b) ''' [[ 1. 0. 0.] [ 0. 1. 0.]] '''
1.2 多維數(shù)組切片 切片多維數(shù)組比 1D數(shù)組 復(fù)雜一點(diǎn),,并且在使用 NumPy 時(shí)你也會(huì)經(jīng)常需要使用到,。 import numpy as np
# MD Array, a = np.array([[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]])
# MD slicing print(a[0, 1:4]) # [12 13 14] print(a[1:4, 0]) # [16 21 26] print(a[::2, ::2]) # [[11 13 15] # [21 23 25] # [31 33 35]] print(a[:, 1]) # [12 17 22 27 32]
通過(guò)對(duì)每個(gè)以逗號(hào)分隔的維度執(zhí)行單獨(dú)的切片,你可以對(duì)多維數(shù)組進(jìn)行切片,。因此,,對(duì)于2D數(shù)組,我們的第一片定義了行的切片,,第二片定義了列的切片,。 1.3 數(shù)組屬性 在使用 NumPy 時(shí),你會(huì)想知道數(shù)組的某些信息,。很幸運(yùn),,在這個(gè)包里邊包含了很多便捷的方法,可以給你想要的信息,。 # Array properties a = np.array([11, 12, 13, 14, 15])
print(type(a)) # <class 'numpy.ndarray'> print(a.dtype) # int32 print(a.size) # 5 print(a.shape) # (5, ) print(a.itemsize) # 4 print(a.ndim) # 1 print(a.nbytes) # 20
# Array properties a = np.array([[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]])
print(type(a)) # <class 'numpy.ndarray'> print(a.dtype) # int32 print(a.size) # 25 print(a.shape) # (5, 5) print(a.itemsize) # 4 print(a.ndim) # 2 print(a.nbytes) # 100
type 正如你在上面的代碼中看到的,NumPy 數(shù)組實(shí)際上被稱為 ndarray,。shape 數(shù)組的形狀是它有多少行和列,,上面的數(shù)組有5行和5列,所以它的形狀是(5,,5),。
itemsize 屬性是每個(gè)項(xiàng)占用的字節(jié)數(shù)。這個(gè)數(shù)組的數(shù)據(jù)類型是int32 ,,一個(gè)int32 中有32位,,一個(gè)字節(jié)中有8位,除以32除以8,,你就可以得到它占用了多少字節(jié),,在本例中是4。
ndim 屬性是數(shù)組的維數(shù),。這個(gè)有2個(gè),。例如,向量只有1,。
nbytes 屬性是數(shù)組中的所有數(shù)據(jù)消耗掉的字節(jié)數(shù),。
2. 使用數(shù)組 2.1 基本運(yùn)算符 import numpy as np
# Basic Operators a = np.arange(25) a = a.reshape((5, 5)) print(a)
''' [[ 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]] ''' b = np.array([10, 62, 1, 14, 2, 56, 79, 2, 1, 45, 4, 92, 5, 55, 63, 43, 35, 6, 53, 24, 56, 3, 56, 44, 78]) b = b.reshape((5, 5)) print(b)
''' [[10 62 1 14 2] [56 79 2 1 45] [ 4 92 5 55 63] [43 35 6 53 24] [56 3 56 44 78]] '''
print(a + b) print(a - b) print(a * b) print(a / b) print(a ** 2) print(a < b) print(a > b) print(a.dot(b))
reshape(a, newshape[, order]) 在不更改數(shù)據(jù)的情況下為數(shù)組賦予新的形狀。dot(a, b[, out]) 函數(shù)計(jì)算兩個(gè)矩陣的乘積,,如果是一維數(shù)組則是它們的點(diǎn)積,。
除了 dot() 之外,這些操作符都是對(duì)數(shù)組進(jìn)行逐元素運(yùn)算,。 2.2 數(shù)組特殊運(yùn)算符 import numpy as np
a = np.arange(9) a = np.reshape(a, [1, 9]) print(a) # [[0 1 2 3 4 5 6 7 8]]
print(np.sum(a)) # 36 print(np.min(a)) # 0 print(np.max(a)) # 8 print(np.cumsum(a)) # [ 0 1 3 6 10 15 21 28 36]
a = np.reshape(a, [3, 3]) print(a) ''' [[0 1 2] [3 4 5] [6 7 8]] ''' print(np.sum(a)) # 36 print(np.min(a)) # 0 print(np.max(a)) # 8 print(np.cumsum(a)) # [ 0 1 3 6 10 15 21 28 36]
print(np.sum(a, axis=0)) # [ 9 12 15] print(np.sum(a, axis=1)) # [ 3 12 21]
print(np.min(a, axis=0)) # [0 1 2] print(np.min(a, axis=1)) # [0 3 6]
print(np.max(a, axis=0)) # [6 7 8] print(np.max(a, axis=1)) # [2 5 8]
print(np.cumsum(a, axis=0)) ''' [[ 0 1 2] [ 3 5 7] [ 9 12 15]] ''' print(np.cumsum(a, axis=1)) ''' [[ 0 1 3] [ 3 7 12] [ 6 13 21]] '''
sum() ,、min() 和max() 函數(shù)的作用非常明顯。將所有元素相加,,找出最小和最大元素,。然而,cumsum() 函數(shù)就不那么明顯了,。它將像sum() 這樣的每個(gè)元素相加,,但是它將當(dāng)前元素之前的和加到當(dāng)前元素上。
3. 索引進(jìn)階 3.1 花式索引 花式索引 是獲取數(shù)組中我們想要的特定元素的有效方法,,即使用我們想要檢索的特定索引序列對(duì)數(shù)組進(jìn)行索引,,返回我們索引的元素的列表。 import numpy as np
# Fancy indexing a = np.arange(0, 100, 10) indices = [1, 5, -1] b = a[indices] print(a) # [ 0 10 20 30 40 50 60 70 80 90] print(b) # [10 50 90]
b = a[np.array(indices)] print(b) # [10 50 90]
3.2 布爾屏蔽 布爾屏蔽 允許我們根據(jù)我們指定的條件檢索數(shù)組中的元素,。 import numpy as np
import matplotlib.pyplot as plt
# Boolean masking a = np.linspace(0, 2 * np.pi, 50) b = np.sin(a) print(len(a)) # 50
plt.plot(a, b) mask = b >= 0 print(len(a[mask])) # 25 print(mask) ''' [ True True True True True True True True True True True True True True True True True True True True True True True True True False False False False False False False False False False False False False False False False False False False False False False False False False] ''' plt.plot(a[mask], b[mask], 'bo')
mask = np.logical_and(b >= 0, a <= np.pi / 2) print(mask) ''' [ True True True True True True True True True True True True True False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False] '''
plt.plot(a[mask], b[mask], 'go') plt.show()
我們利用這些條件來(lái)選擇圖上的不同點(diǎn),。藍(lán)色點(diǎn)(在圖中還包括綠點(diǎn),但綠點(diǎn)掩蓋了藍(lán)色點(diǎn)),,顯示值 大于0 的所有點(diǎn),。綠色點(diǎn)表示值 大于0 且 小于0.5π 的所有點(diǎn),。 numpy.pi pi = 3.1415926535897932384626433…
numpy.e e = 2.71828182845904523536028747135266249775724709369995…
sin(x, /[, out, where, casting, order, …]) Trigonometric sine, element-wise.
logical_and(x1, x2, /[, out, where, …]) 按元素計(jì)算x1和x2的真值。
logical_or(x1, x2, /[, out, where, casting, …]) 按元素計(jì)算x1或x2的真值,。
logical_not(x, /[, out, where, casting, …]) 計(jì)算非x元素的真值,。
logical_xor(x1, x2, /[, out, where, …]) 按元素計(jì)算x1 XOR x2的真值。
3.3 缺省索引 不完全索引是從多維數(shù)組的第一個(gè)維度獲取索引或切片的一種方便方法,。 import numpy as np
a = np.array([[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]]) print(a[3]) # [26 27 28 29 30]
print(a[3:]) ''' [[26 27 28 29 30] [31 32 33 34 35]] ''' print(a[:3]) ''' [[11 12 13 14 15] [16 17 18 19 20] [21 22 23 24 25]] '''
print(a[a >= 25]) # [25 26 27 28 29 30 31 32 33 34 35]
3.4 Where 函數(shù) where() 函數(shù)是另外一個(gè)根據(jù)條件返回?cái)?shù)組中的值的有效方法,。只需要把條件傳遞給它,,它就會(huì)返回一個(gè)使得條件為真的元素的列表,。
import numpy as np
# Where a = np.arange(0, 100, 10) print(a) # [ 0 10 20 30 40 50 60 70 80 90]
b = np.where(a < 50) c = np.where(a >= 50)[0] print(b) # (array([0, 1, 2, 3, 4], dtype=int64),) print(c) # [5 6 7 8 9] print(np.array(b) * 2) # [[0 2 4 6 8]]
a = np.array([[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]]) b = np.where(a > 28) c = np.where(a > 28)[1] print(b) # (array([3, 3, 4, 4, 4, 4, 4], dtype=int64), array([3, 4, 0, 1, 2, 3, 4], dtype=int64))
print(np.array(b)) ''' [[3 3 4 4 4 4 4] [3 4 0 1 2 3 4]] ''' print(c) # [3 4 0 1 2 3 4]
4. 其它 import numpy as np
randMat = np.mat(np.random.rand(4, 4))
print(randMat) ''' [[ 0.27583095 0.85371896 0.04477732 0.0351685 ] [ 0.99631911 0.87780066 0.40519399 0.91468947] [ 0.29717361 0.86168002 0.28151676 0.08364942] [ 0.29388903 0.74111371 0.45270016 0.4220726 ]] '''
invRandMat = randMat.I print(invRandMat) ''' 求逆矩陣
[[-2.95048939 1.59328107 4.89236828 -4.17662009] [ 2.24072267 -0.50472824 -1.59788475 1.22379156] [-4.67532022 -0.10375646 5.07432839 -0.39124946] [ 3.13454227 -0.11186758 -6.04338775 3.54823514]] '''
myEye = randMat * invRandMat print(myEye)
''' 矩陣乘法
[[ 1.00000000e+00 5.55111512e-17 -2.22044605e-16 -2.22044605e-16] [ 0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00] [ 0.00000000e+00 1.11022302e-16 1.00000000e+00 -2.22044605e-16] [ 0.00000000e+00 0.00000000e+00 -8.88178420e-16 1.00000000e+00]] '''
print(myEye - np.eye(4))
''' [[ 0.00000000e+00 5.55111512e-17 -2.22044605e-16 -2.22044605e-16] [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] [ 0.00000000e+00 1.11022302e-16 2.22044605e-16 -2.22044605e-16] [ 0.00000000e+00 0.00000000e+00 -8.88178420e-16 0.00000000e+00]] '''
總結(jié)如你所見(jiàn),NumPy 在其提供的庫(kù)函數(shù)方面非常強(qiáng)大,。本文僅供學(xué)員們?nèi)腴T使用,,我們?cè)趯?xiě)機(jī)器學(xué)習(xí)的算法時(shí),慢慢補(bǔ)充完善,。今天就到這里吧,!See You!
參考文獻(xiàn) https://www./guides/different-ways-create-numpy-arrays https://www./reference/constants.html https://www./article/basics/an_introduction_to_scientific_python_numpy.html
|