NumPy 數組基礎
因為前天說了shap,這里涉及到數據形狀尺寸問題,所以需要在這一節說清楚,后續的神經網絡我們將要和他天天打交道。
知識點:
- numpy數組的創建:簡單創建、隨機創建、遍歷、運算
- numpy數組的索引:一維、二維、三維
- SHAP值的深入理解
作業:今日知識點比較多,好好記憶下
1. 理解數組的維度 (Dimensions)
NumPy 數組的維度或稱為軸 (Axis)的概念,與我們日常理解的維度非常相似。直觀判斷:數組的維度層數通常可以通過打印輸出時中括號 `[]` 的嵌套層數來初步確定:
?一層 `[]`:一維數組。兩層 `[]`:二維數組。三層 `[]`:三維數組,依此類推。
2. NumPy 數組與深度學習 Tensor 的關系
在后續進行頻繁的數學運算時,尤其是在深度學習領域,對 NumPy 數組的理解非常有幫助,因為 PyTorch 或 TensorFlow 中的Tensor張量本質上可以視為支持 GPU 加速和自動微分的 NumPy 數組。掌握 NumPy 的基本操作,能極大地降低學習 Tensor 的門檻。關于 NumPy 更深入的性質,我們留待后續探討。
3. 一維數組 (1D Array)
一維數組在結構上與 Python 中的列表(List)非常相似。它們的主要區別在于:
打印輸出格式: 當使用 `print()` 函數輸出時:NumPy 一維數組的元素之間默認使用空格分隔。Python 列表的元素之間使用逗號分隔。
# 分清楚列表和數組的區別
print([7, 5, 3, 9]) # 輸出: [7, 5, 3, 9](逗號分隔)
print(np.array([7, 5, 3, 9])) # 輸出: [7 5 3 9](空格分隔)
?4. 二維數組 (2D Array)
二維數組可以被看作是“數組的數組”或者一個矩陣。其結構由兩個主要維度決定:
- 行數:代表整個二維數組中包含多少個一維數組。
- 列數:代表每個一維數組(也就是每一行)中包含多少個元素。
值得注意的是,二維數組不一定是正方形(即行數等于列數),它可以是任意的 `n * m` 形狀,其中 `n` 是行數,`m` 是列數。
?5. 數組的創建
NumPy 的 `array()` 函數非常靈活,可以接受各種“序列型”對象作為輸入參數來創建數組。這意味著你可以將 Python 的列表 (List)、元組 (Tuple),甚至其他的 NumPy 數組等數據結構直接傳遞給 `np.array()` 來創建新的 NumPy 數組。
一、簡單賦值創建
import numpy as np
a = np.array([2,4,6,8,10,12]) # 創建一個一維數組
b = np.array([[2,4,6],[8,10,12]]) # 創建一個二維數組
print(a)
print(b)# ------ 以下是結果 -------
[ 2 4 6 8 10 12]
[[ 2 4 6][ 8 10 12]]
最重要的是數組的形狀要搞清楚
a.shape # 結果是(6,),1個數字表示1維
b.shape # 結果是(2, 3),2個數字表示2維
區分一下一維數組(6,)和二維數組(1,6)、(6,1)
# 一維數組 (6,)
a = np.array([1,2,3,4,5,6])
# 二維數組 (1,6)
b = np.array([[1,2,3,4,5,6]])
# 二維數組 (6,1)
c = np.array([[1],[2],[3],[4],[5],[6]])
二、全零數組、全一數組、順序數組
zeros = np.zeros((2, 3)) # 創建一個2行3列的全零矩陣
zeros
# -------- 以下是輸出結果 --------
array([[0., 0., 0.],[0., 0., 0.]])ones = np.ones((3,)) # 創建一個形狀為(3,)的全1數組
ones
# -------- 以下是輸出結果 --------
array([1., 1., 1.])arange = np.arange(1, 10) # 創建一個從1到10的數組
arange
# -------- 以下是輸出結果 --------
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
1. 是浮點數(float)的簡寫形式等價于 1.0,表示這是一個浮點數而非整數,NumPy的 ones()/zeros() 等函數默認會創建浮點型數組,這是科學計算的常見需求;arange()默認創建整數型數組,設計用于生成序列,常用于索引等整數場景,np.arange()?只能直接創建一維數組,但通過reshape等后續操作可自由轉換維度,常用于創建二維數組和三維數組
arr3d = np.arange(3 * 4 * 5).reshape((3, 4, 5))
# 生成從0-59的連續一維數組,再重塑為3×4×5的三維數組(層數, 行數, 列數)# ---------- 以下為結果 -----------
array([# 第0層 (shape: 4x5)[[ 0, 1, 2, 3, 4],[ 5, 6, 7, 8, 9],[10, 11, 12, 13, 14],[15, 16, 17, 18, 19]],# 第1層 [[20, 21, 22, 23, 24],[25, 26, 27, 28, 29],[30, 31, 32, 33, 34],[35, 36, 37, 38, 39]],# 第2層[[40, 41, 42, 43, 44],[45, 46, 47, 48, 49],[50, 51, 52, 53, 54],[55, 56, 57, 58, 59]]
])
三、隨機創建數組
1. 在后續深度學習中,我們經常需要對數據進行隨機化處理,以確保模型的泛化能力。
2. 為了測試很多函數的性能,往往需要隨機化生成很多數據。
- 記憶技巧:
1. 看結尾:
? ?- "int" → 整數
? ?- "n" → 正態(normal)
2. 看前綴:
? ?- 純"random" → Python基礎隨機
? ?- "np.random" → NumPy增強版
3. 功能差異:
? ?- `rand()`和`random()`都是均勻分布,但`rand()`能直接生成數組
? ?- `randn()`生成的數據會有正有負,其他方法都是非負數
來應用一下:
import numpy as np
np.random.seed(42) # 設置隨機種子以確保結果可重復# 生成10個語文成績(正態分布,均值75,標準差10)
chinese_scores = np.random.normal(75, 10, 10).round(1)
# 第一個參數75為均值。第二個參數10為標準差,第三個參數10為數組大小
# .normal() 生成原始隨機數(可能含多位小數) .round(1) 將結果四舍五入保留1位小數# 找出最高分和最低分及其索引
max_score = np.max(chinese_scores)
max_index = np.argmax(chinese_scores)
min_score = np.min(chinese_scores)
min_index = np.argmin(chinese_scores)print(f"所有成績: {chinese_scores}")
print(f"最高分: {max_score} (第{max_index}個學生)")
print(f"最低分: {min_score} (第{min_index}個學生)")# ---------- 以下為結果 ----------
所有成績: [80. 73.6 81.5 90.2 72.7 72.7 90.8 82.7 70.3 80.4]
最高分: 90.8 (第6個學生)
最低分: 70.3 (第8個學生)
四、數組的運算
很簡單,全部參考線代的矩陣計算規則即可,但注意直接用' * '、' / '符號進行的是逐元素乘除法,矩陣乘法是' @ '運算符,矩陣除法要先求逆再矩陣乘法,就是注意一下 NumPy 的?*?相當于MATLAB的?.*,而?@?相當于MATLAB的?*
五、數組的索引
1.一維數組
對于一維數組取一個元素的索引來說,跟列表差不多
整數數組進行索引一次性取多個元素:語法是 arr1d[[index1, index2, ...]]
arr1d[[3, 5, 8]] # 取出數組中索引為 3, 5, 8 的元素
切片進行索引一次性取多個元素:語法是 arr1d[start : stop],假如步長想要自己設置
arr1d[start : stop : step]
arr1d[2:6] # 取出索引為2到5的元素(不包括索引6的元素,取左不取右)arr1d[:5] # 取出數組中從頭到索引 5 (不包含 5) 的元素arr1d[4:] # 取出數組中從索引 4 到結尾的元素arr1d[:] # 取出全部元素arr1d[::2] # 取出數組中所有偶數索引對應的元素 (即索引 0, 2, 4, 6, ...)
2.二維數組
索引順序:在二維數組 arr2d 里,第一個索引值代表行,第二個索引值代表列。比如 arr2d[i ,?j] ,i 是行索引,j 是列索引
arr2d[1, :] # 取出第 2 行 (索引為 1) 的所有元素,也可以省略后面的:成arr2d[1]arr2d[:, 2] # 取出第 3 列 (索引為 2) 的所有元素arr2d[[0, 2], :] # 使用整數數組作為行索引,取出由第 1 行和第 3 行的元素arr2d[:, [1, 3]] # 使用整數數組作為列索引,取出由第 2 列和第 4 列的元素arr2d[1:3, 1:3] # 使用切片作為索引,取出一個 2x2 的子矩陣
3.三維數組
和二維數組的索引差不多
arr3d = np.arange(3 * 4 * 5).reshape((3, 4, 5))
# 生成從0-59的連續一維數組,再重塑為3×4×5的三維數組(層數, 行數, 列數)# ---------- 以下為結果 -----------
array([# 第0層 (shape: 4x5)[[ 0, 1, 2, 3, 4],[ 5, 6, 7, 8, 9],[10, 11, 12, 13, 14],[15, 16, 17, 18, 19]],# 第1層 [[20, 21, 22, 23, 24],[25, 26, 27, 28, 29],[30, 31, 32, 33, 34],[35, 36, 37, 38, 39]],# 第2層[[40, 41, 42, 43, 44],[45, 46, 47, 48, 49],[50, 51, 52, 53, 54],[55, 56, 57, 58, 59]]
])arr3d[1, :, :] # 選擇第二層
# --------- 以下為結果 -----------
array([[20, 21, 22, 23, 24],[25, 26, 27, 28, 29],[30, 31, 32, 33, 34],[35, 36, 37, 38, 39]])arr3d[1, 0:2, :]# 使用整數數組 [0, 2] 作為第一個維度 (層) 的索引
# --------- 以下為結果 -----------
array([[20, 21, 22, 23, 24],[25, 26, 27, 28, 29]])arr3d[1, 0:2, 2:4]
# --------- 以下為結果 -----------
array([[22, 23],[27, 28]])
收獲心得:
學完了再調轉回去看看shap庫那一節的shap_values的索引,應該就能搞懂了
@浙大疏錦行