🗺️ 程式互動式地圖
AI 線・NumPy

NumPy 的 shape 與 axis:sum(axis=0) 到底往哪裡壓

看到 (3, 4)、axis=0、reshape(-1, 2)、(n,) 與 (n, 1) 就開始混亂,程式題問「結果的 shape」總是差一點選錯。這一頁把形狀拆成一條一條的軸,讓你看清楚每一行程式讓哪一軸消失、保留或重新排列。

axis 壓縮動畫 reshape 排列實驗(含 -1) shape 判讀:16 張情境卡

💡 先搞懂問題

虛構的「晴空咖啡」店長把 3 間分店、連續 4 天的拿鐵杯數放進一個 NumPy 陣列,印出 sales.shape 是 (3, 4)。他想知道「每一天三家店合計賣多少」,寫了 sales.sum(axis=0),拿到 4 個數字,正確。隔週換同事接手,想算「每一家店四天合計」,心想「0 是第一個,應該就是一列一列加」,也寫了 axis=0,同樣拿到 4 個數字,就把它當成 3 家店的業績貼進報表。程式完全沒有報錯,因為 NumPy 只照你給的 axis 做事,它不知道你心裡想的是哪個方向。

新手在這個主題最常卡在三件事。第一是 axis 的方向感:axis=0 不是「對第 0 列做事」,而是「沿著第 0 軸把資料壓扁」,第 0 軸因此消失。第二是形狀的寫法:(3,)、(3, 1)、(1, 3) 看起來都是「3 個數」,在 NumPy 裡卻是三種不同的東西,scikit-learn 還會因此拒收你的資料。第三是 reshape(-1, 2) 這類寫法:-1 是多少、元素依什麼順序填進新形狀,不清楚就只能用猜的。

先把名詞對好。shape(形狀)是一個 tuple,依序寫出每一個軸(axis,也就是維度)的長度,(3, 4) 代表第 0 軸長 3、第 1 軸長 4;ndim 是軸的數量;size 是元素總數,等於 shape 裡所有數字相乘。sum、mean、max、argmax 這類彙總(reduction)函式的 axis 參數,指定「沿著哪一軸把一整排值合成一個值」,被指定的那一軸會從結果的 shape 裡消失。reshape 則只換排法,不增減元素。

同一串 12 個數字(示意),三種 shape shape (12,):一維,一排 12 格 0 1 2 3 4 5 6 7 8 9 10 11 shape (3, 4):3 列 × 4 欄 shape (2, 2, 3):2 塊 × 2 列 × 3 欄 0 1 2 3 4 5 6 7 8 9 10 11 0 1 2 3 4 5 6 7 8 9 10 11 第 0 塊 第 1 塊 元素與順序 完全相同, 只是解讀方式 不同 sum(axis=0) 剩幾個? (3,) 和 (3, 1) 一樣嗎? reshape(-1, 2) 的 -1?
上面三種 shape 裝的是同一串 0 到 11,記憶體裡的順序一模一樣,差別只在「每一軸多長」。下排三個紅框是新手最常卡住的問題,這一頁的三個實驗室分別回答它們:axis 壓縮器、reshape 排列實驗、shape 判讀卡。

生活比喻:蛋盒與倒進碗裡的蛋

想像蛋行老闆把 12 顆蛋排在一個 3 列、每列 4 格的蛋盒裡。客人問「每一直行有幾斤」,他就把每一直行的 3 顆蛋倒進同一個碗,最後桌上有 4 個碗;客人改問「每一橫列有幾斤」,他就把每一橫列的 4 顆蛋倒進一個碗,桌上只剩 3 個碗。不管哪一種倒法,被倒的那個方向都不見了:倒完直行,就沒有「第幾列」可說;倒完橫列,就沒有「第幾格」可說。同樣這 12 顆蛋,老闆也可以改裝成一排 12 格的長盒,或兩盒各 2 列 3 格,蛋本身一顆都沒變,只是盒子換了。

每一直行倒進一個碗 4 個碗 → sum(axis=0) → shape (4,) 往下的方向(第 0 軸,長 3)被倒掉了 每一橫列倒進一個碗 3 個碗 → sum(axis=1) → shape (3,) 往右的方向(第 1 軸,長 4)被倒掉了 蛋盒=陣列 (3, 4);碗的數量=結果的長度(示意)
左邊沿著直的方向倒,3 列合成 1 列,剩 4 碗;右邊沿著橫的方向倒,4 格合成 1 格,剩 3 碗。記法只有一句:axis 寫幾,第幾軸就被倒掉,結果的 shape 就是把那個數字從 tuple 裡劃掉。
回到程式:蛋盒就是陣列,盒子的規格 (3, 4) 就是 shape。「每一直行倒進一個碗」對應 sales.sum(axis=0):沿著第 0 軸把 3 個值合成 1 個,第 0 軸消失,(3, 4) 劃掉 3 剩下 (4,),也就是每一天的三店合計;「每一橫列倒進一個碗」對應 sales.sum(axis=1),劃掉 4 剩下 (3,),是每一家店的四天合計。改裝成長盒或兩盒,對應的是 reshape(12) 與 reshape(2, 2, 3)。開頭那位同事要的是 3 家店的合計,應該寫 axis=1。

這個比喻有三個地方要小心。第一,桌上的 3 個碗看起來排成一直行,但 (3,) 是一維陣列,沒有「直的」或「橫的」,print 出來永遠是一排 [14 19 21];真的要一個直行,得變成 (3, 1),這正是 keepdims=True 的用途。第二,真的換蛋盒要把蛋一顆顆搬過去,reshape 通常只是換一張「怎麼解讀」的說明書,資料在記憶體裡沒動,回傳的是共用同一塊記憶體的 view。第三,「倒進碗」不一定是加總,也可以是平均(mean)、找最大(max),或回報「最大的那顆在第幾格」(argmax),但被壓掉的軸都一樣會消失。

🎮 互動實驗室一:axis 壓縮器

下面兩個陣列是晴空咖啡的拿鐵杯數(示意):A 是 3 間分店 × 4 天,B 是把兩週疊起來的 2 週 × 3 間分店 × 4 天。選陣列、運算與 axis,左邊會用同一種顏色標出「會被合成同一個值」的格子,再一組一組播放壓縮過程;右邊同步顯示那一行 Python、結果的 shape 與 print 出來的樣子。勾選 keepdims 可以比較被壓掉的軸「消失」與「留下長度 1」的差別,選到不存在的軸會看到真的錯誤訊息。

import numpy as np
A = np.array([[3, 7, 2, 2],    # 分店 0 的 4 天杯數(示意,單位:十杯)
              [6, 2, 8, 3],    # 分店 1
              [3, 9, 5, 4]])   # 分店 2 → A.shape 是 (3, 4)
B = np.stack([A, [[4, 6, 4, 1],
                  [2, 8, 6, 5],
                  [6, 1, 8, 3]]])  # 第 0 週與第 1 週疊起來 → B.shape 是 (2, 3, 4)
陣列
運算
axis

輸入

結果 (4,)


      
畫面說明:載入中。

🎮 互動實驗室二:reshape 排列實驗

從 x = np.arange(12) 出發,12 塊數字磚依序是 0 到 11。選新形狀的維度數,再替每一軸挑長度(可以挑 -1 讓 NumPy 自己算),或直接按下方的常見寫法。數字磚會飛到新位置:NumPy 預設照 C 順序(列優先,最右邊的軸變化最快)一格一格填進去。形狀不合法時,畫面會搖一下,並顯示 NumPy 實際丟出的錯誤訊息。2 維的結果可以勾選「對照 .T」,比較 reshape 與轉置排出來有什麼不同。

維度數
原本(12,)
新的 shape(3, 4)
-1 算出—


  
畫面說明:載入中。

🎮 互動實驗室三:shape 判讀情境卡

每張卡給一小段程式,問最後那一行得到的 shape。先寫下原本的 shape,再判斷這一行屬於哪一類操作:彙總、索引、插入新軸、轉置、reshape 或攤平。選完會說明正解為什麼是它;選錯時會說明你選的那個 shape 是哪一種寫法才會得到。右邊的口訣會亮起這張卡用到的規則。

答對 0 / 0
連續答對 0
判讀口訣
畫面說明:先寫下原本的 shape。

📘 原理補完

1. shape、ndim、size:先數有幾條軸

NumPy 文件把陣列的每一個維度稱為一條軸(axis),編號從 0 開始,由外往內。B.shape 是 (2, 3, 4),代表第 0 軸長 2(兩週)、第 1 軸長 3(三間分店)、第 2 軸長 4(四天)。ndim 是 shape 的長度,也就是軸的數量;size 是所有長度相乘的元素總數 24;len(B) 只回報第 0 軸的長度 2。axis 也能用負數從右邊數,axis=-1 永遠是最後一軸,在不確定陣列有幾維的函式裡特別好用。

B.shape = ( 2 , 3 , 4 ) axis 0(或 -3)2 週 axis 1(或 -2)3 間分店 axis 2(或 -1)4 天 B[0] 第 0 週 B[1] 第 1 週 axis 1 axis 2 axis 0 ndim = 3(軸的數量) size = 2 × 3 × 4 = 24 len(B) = 2(只看第 0 軸)
shape 的每一個數字都是一條軸的長度,從左到右是 axis 0、1、2,也可以從右邊用 -1、-2、-3 數。下方的箭頭是同一件事的空間畫法:axis 0 跨過「塊」、axis 1 往下、axis 2 往右。軸的意義(週、分店、天)是你建立資料時決定的,NumPy 本身並不知道。

2. axis:被指定的軸會消失

sum、mean、max、min、argmax、std 這些彙總函式都遵守同一條規則:沿著 axis 指定的那一軸,把一整排值合成一個值,所以那一軸會從結果的 shape 中消失,其餘的軸維持原本的順序。把 shape 寫出來、劃掉被指定的那個數字,剩下的就是答案。A 是 (3, 4),A.sum(axis=0) 劃掉 3 得 (4,),A.sum(axis=1) 劃掉 4 得 (3,)。axis 也可以給 tuple 一次壓掉好幾軸,例如影像批次 (8, 3, 32, 32) 用 axis=(2, 3) 壓掉高與寬,得到每張圖每個通道的平均 (8, 3)。不給 axis(等於 axis=None)就是所有軸一起壓掉,結果是一個 shape 為 () 的純量。

A.sum(axis=0) A.sum(axis=1) 3 7 2 2 6 2 8 3 3 9 5 4 12 18 15 9 3 7 2 2 6 2 8 3 3 9 5 4 14 19 21 (3, 4) 劃掉 3 → (4,) 每一天的三店合計 (3, 4) 劃掉 4 → (3,) 每間店的四天合計,印出來仍是一排
同色的格子會合成同一個值。左邊 axis=0 沿著往下的方向合併,同一欄同色;右邊 axis=1 沿著往右的方向合併,同一列同色。右邊的 3 個結果雖然來自 3 列,但結果是一維 (3,),print 出來是 [14 19 21] 一排。
B.sum(axis=0) B.sum(axis=1) B.sum(axis=2) 兩週疊成一塊 每週剩一列 每週剩一欄 (3, 4)(2, 4)(2, 3) 劃掉 2:每店每天兩週合計劃掉 3:每週每天三店合計劃掉 4:每週每店四天合計
三維也是同一條規則。最上排是 B 的兩塊(第 0 週、第 1 週),箭頭下方是壓縮後剩下的形狀。注意 axis=1 與 axis=2 的結果,第 0 軸(週)都還在最前面:被壓掉的軸消失,其他軸的順序不變。數字為示意。

argmax 是最容易看錯的一個。它回傳的不是最大值,而是最大值在那一軸上的位置(從 0 起算),遇到同樣大的值取第一個。不給 axis 時,NumPy 先把陣列攤平成一維再找,所以 A.argmax() 回傳 9,不是 (2, 1);要換回列與欄得用 np.unravel_index(9, A.shape)。分類模型的 probs.argmax(axis=1) 是每一列(每一筆樣本)機率最高的類別編號,結果長度等於樣本數。

3. keepdims:把被壓掉的軸留成長度 1

有時候你希望壓完之後維度數不變,例如每一列的平均要拿回去和原陣列相減。keepdims=True 讓被壓掉的軸留下來、長度變成 1:A.sum(axis=1) 是 (3,),加上 keepdims 變成 (3, 1),一個直行。這個差別在下一步就看得出來:A - A.mean(axis=1, keepdims=True) 能讓每一列各自減掉自己的平均,A - A.mean(axis=1) 卻會因為 (3, 4) 與 (3,) 形狀對不上而丟出 ValueError,背後的規則就是廣播(broadcasting),在姊妹頁「NumPy 廣播」有完整的互動說明。

A.sum(axis=1) A.sum(axis=1, keepdims=True) 14 19 21 14 19 21 (3,) (3, 1) 一維:只有長度,沒有直橫 二維:3 列 1 欄的直行 A − A.mean(axis=1) ✗ (3, 4) 與 (3,):最右邊 4 對 3,報錯 A − A.mean(axis=1, keepdims=True) ✓ (3, 4) 與 (3, 1):每列減自己的平均
左右兩邊的數字完全一樣,差在形狀。keepdims=True 保留了「第 1 軸,長度 1」,結果仍是二維,才能和原本的 (3, 4) 一列對一列運算。標準化、歸一化這類「先彙總再拿回去算」的寫法,最常需要它。

4. reshape、-1 與 C 順序

reshape 不改變元素,也不改變元素在記憶體中的先後,只改變「每一軸多長」的解讀方式,所以新舊 shape 的元素總數必須相同。填入新形狀的順序預設是 C 順序(列優先,row-major):最右邊的軸變化最快,先填滿第 0 列的每一格,再換第 1 列。某一軸寫 -1,代表「其他軸決定後,這一軸自動算」,-1 只能出現一次,而且必須除得盡,否則會得到 cannot reshape array of size 12 into shape (5,newaxis) 這類 ValueError,訊息裡的 newaxis 就是你寫 -1 的那一軸。能不複製時,reshape 回傳的是 view,修改它會改到原陣列。

轉置 .T 也能把 (3, 4) 變成 (4, 3),但做的事完全不同:它把軸的順序倒過來,原本的第 0 欄變成新的第 0 列,資料的相對位置跟著翻轉。考題常把兩者放在一起當干擾選項,看下圖就知道內容不一樣。

x.reshape(3, 4)x.reshape(4, 3)x.reshape(3, 4).T 0 1 2 3 4 5 6 7 8 9 10 11 0 1 2 3 4 5 6 7 8 9 10 11 0 4 8 1 5 9 2 6 10 3 7 11 依序填:一列填滿再換下一列 (4, 3):第 0 列是 0 1 2 (4, 3):第 0 列是 0 4 8 形狀相同、內容不同 reshape 照原順序重排;.T 把列與欄互換
同一個 x = np.arange(12)。左邊與中間都是照 0、1、2…的順序一列一列填;右邊的 .T 把左邊的欄變成列,第 0 列是原本的第 0 欄 0、4、8。顏色代表元素原本在 (3, 4) 裡的第幾列,可以看出轉置把同一列的元素分散到不同列。

要把多維攤平成一維有三種寫法:reshape(-1)、ravel() 與 flatten(),結果的 shape 都一樣。差別在記憶體:flatten 一定複製一份新的;ravel 和 reshape 能不複製就回傳 view,例如對轉置後的陣列攤平就不得不複製。另外別把 reshape 和 ndarray.resize 搞混,後者會就地改形狀,而且允許增減元素。

5. 一維 (n,)、直行 (n, 1)、橫列 (1, n)

這三種形狀都裝著 n 個數字,卻是三種東西。(n,) 只有一條軸,沒有「直」或「橫」可言,.T 對它沒有任何效果;(n, 1) 是 n 列 1 欄的直行;(1, n) 是 1 列 n 欄的橫列。scikit-learn 的特徵矩陣 X 一律要求二維 (樣本數, 特徵數),就算只有一個特徵也一樣;目標 y 則通常是一維。把一維的身高陣列直接丟進 LinearRegression().fit,會得到 ValueError: Expected 2D array, got 1D array instead,訊息後半段直接建議:只有一個特徵用 reshape(-1, 1),只有一筆樣本用 reshape(1, -1)。兩者 shape 不同,意義也完全相反。

hh.reshape(-1, 1)h.reshape(1, -1) 150 162 171 158 150 162 171 158 150 162 171 158 (4,) (4, 1) (1, 4) 一維:只有長度 4 .T 沒有效果 4 個樣本 × 1 個特徵 1 個樣本 × 4 個特徵 scikit-learn 的 X 要 (樣本數, 特徵數):只有一個特徵時用 reshape(-1, 1) 直接傳一維的 h → ValueError: Expected 2D array, got 1D array instead
四位顧客的身高(示意)。左邊圓角的格子表示一維陣列沒有方向;中間綠色是「一人一列」的直行,這才是 scikit-learn 想要的單一特徵 X;右邊橘色是「一列裝四個特徵」,模型會以為只有一位顧客。

6. 索引會不會讓軸消失

中括號裡每一個位置對應一條軸。放整數,那一軸就被「選定」而消失;放切片(:、0:1、::2),那一軸保留,只是長度可能變短;放 list 或陣列(花式索引,advanced indexing),那一軸也保留,長度等於 list 的長度;放 None(也就是 np.newaxis),就在那個位置插入一條長度 1 的新軸。沒寫到的後面幾軸視同 :,所以 X[0] 等於 X[0, :]。

X (4, 3) 第 0 欄 ← 第 0 列 X[:, 0] X[:, [0]] X[:, 0:1] X[0] → (4,) → (4, 1) → (4, 1) → (3,) 整數 0:第 1 軸消失,變一維 list:保留第 1 軸 切片:保留第 1 軸 整數 0 放在第 0 個位置:第 0 軸消失
紫色是被選出的第 0 欄,黃色是第 0 列。同樣挑出第 0 欄,用整數得到圓角的一維 (4,),用 list 或切片得到方角的直行 (4, 1)。實務上兩者還有一個差別:切片回傳 view,list 索引回傳 copy。

7. 一張表與四個步驟

把前面的規則整理成一張表。範例統一假設 X.shape 是 (4, 3),每一列的結果都用 python3 實際執行確認過。

類型寫法結果 shape規則
彙總X.sum(axis=0)(3,)被指定的軸消失
彙總+keepdimsX.sum(axis=1, keepdims=True)(4, 1)被指定的軸留下長度 1
全部彙總X.sum()、X.max()()axis=None:所有軸消失,得到純量
整數索引X[0]、X[:, 0](3,)、(4,)放整數的那一軸消失
list 索引X[:, [0]]、X[[0, 2]](4, 1)、(2, 3)保留那一軸,長度=list 長度(回傳 copy)
切片X[:, 0:1](4, 1)保留那一軸,長度=切到的個數(回傳 view)
插入新軸X[np.newaxis]、X[:, :, None](1, 4, 3)、(4, 3, 1)在 None 的位置插入長度 1
轉置X.T(3, 4)軸的順序倒過來;一維不變
reshapeX.reshape(2, -1)(2, 6)總數不變,-1 自動算
攤平X.reshape(-1)、X.ravel()、X.flatten()(12,)變成一維;flatten 一定複製
① 寫下原本的 shape,標上 axis 編號 ② 這一行是哪一類操作? 彙總 axis= 索引 [ ] reshape/攤平 轉置 .T 該軸消失keepdims 留 1None 全部消失 整數:消失切片、list:保留None:插入 1 總數不變-1 自動算flatten:一維 軸順序倒過來(a, b) → (b, a)一維不變 ③ 寫出新 shape,再推下一行
讀一段程式時,每一行都套一次這個流程,把中間結果的 shape 寫在旁邊。多數 shape 題只是把三、四行串在一起,一行一行推就不會亂。
  1. 寫下原本的 shape,在每個數字底下標上 axis 編號(0、1、2…,負數從右邊數)。
  2. 判斷這一行屬於彙總、索引、reshape 或轉置,套用上表的規則,寫出新的 shape。
  3. 有好幾行就一行一行往下推,不要在腦中一次跳到最後。
  4. 最後檢查合理性:reshape 前後元素總數相同;要餵給 scikit-learn 的 X 是二維、LSTM 是三維 (批次, 時間步, 特徵)、PyTorch 的 Conv2d 是四維 (N, C, H, W)。

8. 完整範例

第一段把 axis、keepdims、argmax 的規則一次跑過;第二段是 reshape、np.newaxis 與 scikit-learn 的二維要求;第三段是深度學習常見的多維形狀。註解裡的輸出都是 NumPy 2.4、scikit-learn 1.8 實際執行的結果。

import numpy as np
A = np.array([[3, 7, 2, 2],
              [6, 2, 8, 3],
              [3, 9, 5, 4]])           # 3 間分店 × 4 天(示意)
print(A.shape, A.ndim, A.size)        # (3, 4) 2 12
print(A.sum(axis=0))                  # 劃掉第 0 軸 → (4,):[12 18 15  9]
print(A.sum(axis=1))                  # 劃掉第 1 軸 → (3,):[14 19 21]
print(A.sum(axis=-1))                 # -1 是最後一軸,這裡等於 axis=1
print(A.mean(axis=1, keepdims=True).shape)  # (3, 1):被壓的軸留下長度 1
print(A.argmax(axis=1))               # 每列最大值的位置 [1 2 1]
print(A.argmax())                     # 不給 axis:攤平後的位置 9,不是 (2, 1)
print(np.unravel_index(A.argmax(), A.shape))  # 換回 (列, 欄):(np.int64(2), np.int64(1))
import numpy as np
from sklearn.linear_model import LinearRegression
x = np.arange(12)
print(x.reshape(3, 4)[1])            # C 順序:第 1 列是 [4 5 6 7]
print(x.reshape(-1, 2).shape)        # -1 = 12 ÷ 2 = 6 → (6, 2)
print(x.reshape(3, 4).T[0])          # 轉置後的第 0 列是原本的第 0 欄 [0 4 8]
print(np.shares_memory(x, x.reshape(3, 4)))  # True:reshape 回傳 view
h = np.array([150., 162., 171., 158.])   # 4 位顧客的身高(示意)
w = np.array([48., 55., 66., 52.])       # 體重(示意)
X = h.reshape(-1, 1)                 # (4,) → (4, 1):4 個樣本、1 個特徵
print(X.shape, h[:, np.newaxis].shape)   # (4, 1) (4, 1):兩種寫法相同
model = LinearRegression().fit(X, w) # X 要二維,y 維持一維
print(model.predict([[165.]]).shape) # 預測一筆也要包成二維 → (1,)
import numpy as np
imgs = np.zeros((8, 3, 32, 32))      # 8 張影像(批次, 通道, 高, 寬)
print(imgs[0].shape)                 # 整數索引讓第 0 軸消失 → (3, 32, 32)
print(imgs[:1].shape)                # 切片保留該軸 → (1, 3, 32, 32)
print(imgs.mean(axis=(2, 3)).shape)  # 一次壓掉高與寬 → (8, 3)
X = np.zeros((100, 3))
print(X[:, 0].shape, X[:, [0]].shape, X[:, 0:1].shape)  # (100,) (100, 1) (100, 1)
print(X.T.shape, X[:, 0].T.shape)    # (3, 100);一維轉置沒有效果 (100,)
print(X.flatten().shape)             # 攤平成一維 (300,),flatten 一定複製

9. pandas 的 axis 與 groupby

pandas 沿用同一套 axis 觀念:df.sum() 預設 axis=0,每一欄加總、得到以欄名為索引的 Series;df.sum(axis=1)(也可寫 axis="columns")是每一列加總。容易混淆的是 df.drop("a", axis=1):這裡的 axis 指「要刪的標籤在哪一條軸上」,所以 axis=1 是刪掉欄,和彙總函式「沿著哪一軸壓」的讀法不同,建議直接寫 drop(columns="a") 避免誤會。groupby 也可以看成一種壓縮:它不是把整條軸壓成一個值,而是依某一欄的鍵把列分組,每組壓成一列,詳細寫法在地圖的「groupby 與彙總」節點。

容易寫錯或考錯的地方

axis=0 的結果長度等於欄數:(3, 4) 對 axis=0 彙總得到 4 個值。干擾選項常把 axis=0 說成「每一列的總和」,或把 (4,) 寫成 (3,)。

argmax 回傳位置不是值:不給 axis 時回傳攤平後的位置。選項裡出現「最大值本身」或 (列, 欄) tuple 的,多半是陷阱。

整數索引與切片:X[:, -1, :] 少一軸,X[:, -1:, :] 保留長度 1 的軸。LSTM 取最後一個時間步的題目最常考這一對。

一維轉置:v.T 對 (n,) 沒有效果;想得到直行要用 v[:, None] 或 v.reshape(-1, 1)。

reshape(-1, 1) 與 reshape(1, -1):前者是 n 筆樣本、1 個特徵,後者是 1 筆樣本、n 個特徵。只有一個特徵的 scikit-learn 題目選前者。

reshape 不是轉置:形狀相同不代表內容相同,題目若問「第 0 列是什麼」,要分清楚是照順序重填還是列欄互換。

版本差異:NumPy 2 在互動環境顯示純量時會帶型別,例如 A.sum() 顯示 np.int64(54),print 則仍印出 54。axis 超出範圍時丟出 numpy.exceptions.AxisError,它同時是 ValueError 與 IndexError 的子類別。argmax 與 argmin 從 NumPy 1.22 起才支援 keepdims。

✅ 自我檢測

6 題原創的程式閱讀題,每一題的輸出都用 python3 實際執行確認過。選完立即顯示對錯與解析,全部作答後會出現總分。目前得分:0 / 6

🎯 重點整理

  1. shape 的每個數字是一條軸的長度,由左到右是 axis 0、1、2,也能用 -1 從最後一軸數起。
  2. 彙總函式的 axis:把 shape 裡那個數字劃掉,就是結果的 shape;axis=None 得到純量 ()。
  3. keepdims=True 讓被壓掉的軸留下長度 1,方便和原陣列繼續運算。
  4. argmax 回傳位置;不給 axis 時是攤平後的位置。
  5. reshape 總數不變、照 C 順序重填,-1 自動算且只能一個;它和 .T 形狀可能相同但內容不同。
  6. (n,)、(n, 1)、(1, n) 是三種東西;scikit-learn 的 X 要二維,單一特徵用 reshape(-1, 1)。
  7. 索引:整數讓軸消失,切片與 list 保留,None 插入長度 1。