跳到主要內容

Day 23 線性代數

Day 23 線性代數

引言

從今天開始,我們要花三天的時間,把深度學習背後的數學基礎補齊。很多人在學神經網路時,會覺得「為什麼要學這些?」其實原因很簡單:神經網路本質上就是不斷做矩陣乘法、向量內積與梯度運算。如果對這些運算的意義與性質不熟,看到「形狀不符」或「梯度爆炸」的錯誤訊息時,就只能盲目試錯。

今天的主題是線性代數。我們會從最直觀的向量與矩陣出發,理解加減乘的規則與意義,再學會內積、矩陣乘法、轉置,並用 NumPy 把每個概念用具體的數字算一遍。雖然 NumPy 已經在前幾天介紹過,但今天會用更多「數學意義」的角度去用它。這篇不會列一大堆公式,而是盡量把每個概念都用具體的小數字例子展示,讓你看到結果、對照公式,理解就不會只停留在符號上。

向量:有序排列的一串數字

在資料科學中,向量(vector)就是一組有序的數字,可以用來表示一筆資料的多個特徵。例如一位顧客的「年齡、身高、體重」就可以寫成一個三維向量 [28, 168, 60]。向量空間是 NumPy 一維陣列(ndarray)最直接的數學對應。除了表示資料,向量也常用來表示「方向」與「大小」,這在後續理解梯度時特別重要。

import numpy as np

v = np.array([3, 4])
print("向量 v =", v)
print("維度 =", v.ndim)
print("形狀 =", v.shape)
print("長度 =", np.linalg.norm(v))  # 歐氏長度 sqrt(3^2 + 4^2) = 5

輸出:

向量 v = [3 4]
維度 = 2
形狀 = (2,)
長度 = 5.0

np.linalg.norm() 計算的是歐氏長度,公式是各分量平方相加再開根號。3-4-5 這個經典的直角三角形告訴我們,向量 [3, 4] 的長度剛好是 5,因為 3² + 4² = 5²。這個長度概念在 Day 24 計算梯度時會用到。另一個常用操作是「單位化」,把向量除以自己的長度,讓它的長度變成 1,這樣可以保留方向資訊但去除大小差異。

向量運算:加減、純量乘法、點對點運算

兩個向量只要長度相同,就可以做加減;向量也可以和一個純量(單一數字)相乘。NumPy 對向量運算的處理非常直觀,運算子會自動對應到每個元素。向量加減代表「對應位置的數值增減」,例如 [3, 4] + [1, 2] = [4, 6],就是把兩組數字逐項相加。

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

print("a + b =", a + b)
print("a - b =", a - b)
print("2 * a =", 2 * a)
print("a * b =", a * b)  # 點對點相乘

輸出:

a + b = [5 7 9]
a - b = [-3 -3 -3]
2 * a = [2 4 6]
a * b = [ 4 10 18]

注意 a * b 是「對應元素相乘」,這跟線性代數的內積完全不同。NumPy 用 * 表示 Hadamard 乘積(element-wise);真正的內積(dot product)要用 np.dot() 或 @ 運算子。這個區分非常重要,因為在神經網路中這兩種乘法會在不同的層次出現——點對點相乘常見於激活函式與遮罩,內積則是每一層線性變換的核心。

內積:兩個向量的「相似度」

兩個向量的內積(dot product)定義為對應元素相乘後相加:a · b = a₁b₁ + a₂b₂ + ... + aₙbₙ。在機器學習中,內積常用來表示「兩個特徵向量的相似程度」——值越大,代表兩個向量越接近同一個方向。這個解釋在推薦系統、文件相似度計算中尤其重要。

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

dot1 = np.dot(a, b)
dot2 = a @ b  # 等同於 np.dot
print("內積(np.dot) =", dot1)
print("內積(@ 運算子) =", dot2)

輸出:

內積(np.dot) = 32
內積(@ 運算子) = 32

計算過程:1×4 + 2×5 + 3×6 = 4 + 10 + 18 = 32。內積也能寫成「兩向量長度乘積再乘上夾角的餘弦」,這個性質在之後理解 cosine similarity(文件相似度)時會很關鍵。如果兩個向量互相垂直(夾角 90 度),內積為 0;如果方向完全相反,內積為負數。這些幾何意義在後續解釋「為什麼某些神經網路權重會趨近 0」時會派上用場。實務上推薦系統裡計算「使用者向量與物品向量的相似度」,也是內積的直接應用。值得注意的是,np.dot 與 @ 對一維陣列的行為是相同的,但對二維陣列就會對應到矩陣乘法,這種「依照陣列維度自動切換語意」的設計,是 NumPy 對新手友善但也容易踩坑的地方。

矩陣:二維的數字陣列

矩陣(matrix)就是二維陣列。在資料科學中,一個 m×n 的矩陣通常代表「m 筆資料、每筆 n 個特徵」。Pandas 的 DataFrame 可以想成是「有欄位名稱的矩陣」,但底層運算還是 NumPy。矩陣的概念比向量更高一維,可以同時儲存多筆資料或多組特徵。

A = np.array([
    [1, 2, 3],
    [4, 5, 6]
])

print("矩陣 A =")
print(A)
print("形狀 =", A.shape)
print("轉置後 =")
print(A.T)

輸出:

矩陣 A =
[[1 2 3]
 [4 5 6]]
形狀 = (2, 3)
轉置後 =
[[1 4]
 [2 5]
 [3 6]]

A 是 2×3 矩陣(2 列、3 欄),轉置 A.T 之後變成 3×2 矩陣,原本的列變成欄、欄變成列。轉置在神經網路裡很常用,例如某些運算需要把輸入向量的形狀從「批次×特徵」轉成「特徵×批次」。學神經網路時記住一個原則:「左矩陣的欄數要等於右矩陣的列數」,矩陣乘法才合法。

矩陣乘法:神經網路的核心運算

神經網路最常做的一件事,就是「輸入矩陣乘上權重矩陣」。NumPy 用 @ 或 np.matmul() 進行矩陣乘法;它跟 * 的差異,要特別小心。矩陣乘法在幾何上的意義是「把一個向量透過線性變換映射到另一個空間」,這個觀念會在 Day 32 CNN 章節再次出現。

A = np.array([
    [1, 2],
    [3, 4],
    [5, 6]
])

B = np.array([
    [7, 8, 9],
    [10, 11, 12]
])

print("A 形狀 =", A.shape)
print("B 形狀 =", B.shape)
print("A @ B 形狀 =", (A @ B).shape)
print("A @ B =")
print(A @ B)

輸出:

A 形狀 = (3, 2)
B 形狀 = (2, 3)
A @ B 形狀 = (3, 3)
A @ B =
[[ 27  30  33]
 [ 61  68  75]
 [ 95 106 117]]

矩陣乘法的形狀規則:左矩陣的「欄數」必須等於右矩陣的「列數」,結果的形狀是「左列數 × 右欄數」。這個規則在設計神經網路層時特別重要——每一層權重的形狀必須和輸入的形狀對得上。舉例來說,第一個矩陣乘法的結果 27 是這樣算出來的:1×7 + 2×10 = 27。如果忘了這個規則,就會在 PyTorch 訓練時一直碰到 RuntimeError: mat1 and mat2 shapes cannot be multiplied 的錯誤。

單位矩陣與反矩陣

單位矩陣(identity matrix)是對角線為 1、其他位置為 0 的方陣,扮演乘法中的「1」。反矩陣(inverse)則是讓 A 乘以 A 的反矩陣會得到單位矩陣。理解這兩個概念對之後學習「線性迴歸的解析解」會很有幫助。

I = np.eye(3)
print("3×3 單位矩陣:")
print(I)

A = np.array([
    [4, 7],
    [2, 6]
], dtype=float)

A_inv = np.linalg.inv(A)
print("\nA 反矩陣:")
print(A_inv)
print("\nA @ A_inv:")
print(A @ A_inv)

輸出:

3×3 單位矩陣:
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

A 反矩陣:
[[ 0.6  -0.7]
 [-0.2   0.4]]

A @ A_inv:
[[ 1.  0.]
 [ 0.  1.]]

A 乘上 A 的反矩陣,結果非常接近單位矩陣(由於浮點數誤差可能看到 0.0000001 之類的微小數字,可以用 np.round() 處理)。反矩陣在線性迴歸公式 (XᵀX)⁻¹Xᵀy 中會用到,但實務上會用更穩定的數值方法,例如 np.linalg.solve()。另外要注意,不是每個矩陣都有反矩陣——當矩陣的行列式(determinant)為 0 時,稱為「奇異矩陣」,這時候無法求反矩陣。

結語

今天用 NumPy 把向量、矩陣、內積、轉置、矩陣乘法、單位矩陣、反矩陣都操作了一遍。線性代數看似抽象,但只要把每個概念都寫成 NumPy 程式碼跑一次,數學公式就不再只是符號。下次看到神經網路中的「X @ W + b」這個運算式,就能立刻反應出它的形狀變化與幾何意義。線性代數在機器學習中無所不在——從最基本的線性迴歸到深度學習的卷積運算,背後都是線性變換與矩陣操作。

明天,我們會進入微積分與梯度。理解導數、偏導數與梯度的意義,是看懂「神經網路是怎麼學的」的關鍵。

留言

這個網誌中的熱門文章

Day 2 變數與資料型別

Day 2 變數與資料型別 引言 寫程式的過程中,變數與資料型別是處理資料的基礎。變數是存放資料的容器,資料型別則決定這筆資料有哪些特性、可以進行哪些操作。學會定義變數、認識各種資料型別,是學好 Python 的關鍵一步。 這篇文章會帶你了解 Python 中變數的觀念、如何定義變數,以及常見的資料型別,包括整數、浮點數、字串、布林值,還有串列、元組、字典與集合等容器型別。我們也會介紹變數的命名規則與撰寫風格建議,以及如何用 type() 檢查資料型別。 什麼是變數?如何在 Python 中定義變數 變數是在程式執行時用來存放資料的名稱。透過定義變數,我們可以給一筆資料一個名字,並在程式的其他地方用這個名字取用該筆資料。在 Python 中,變數不需要事先宣告型別,因為 Python 是動態型別語言,變數的型別由指定給它的值決定。 定義變數的基本語法 在 Python 中定義變數非常簡單,只要用賦值符號 = 把值指定給變數即可。例如: x = 5 # 定義變數 x,並把整數 5 賦值給它 name = "Alice" # 定義變數 name,並把字串 "Alice" 賦值給它 在這裡,x 是一個變數,被賦予整數 5;name 是另一個變數,被賦予字串 "Alice"。 變數的更新與覆寫 變數的值可以修改,也就是說,我們可以在程式的不同地方給同一個變數新的值。例如: x = 10 # x 最初被賦予 10 x = 15 # x 的值現在被更新為 15 這樣就能依照需求,在程式執行過程中靈活調整變數的值。 Python 的動態型別系統 Python 和某些靜態型別語言不同,定義變數時不需要宣告型別。賦值時,Python 會根據值自動判斷變數的型別。例如: x = 5 # x 是整數 x = 3.14 # x 變成浮點數 x = "Hi" # x 變成字串 同一個變數在程式執行過程中可以存放不同型別的值,這是 Python 的彈性之一。 常見資料型別 在 Python 中,資料型別決定我們可以對變數進行哪些操作...

Day 1 Python 簡介與環境設定

Day 1 Python 簡介與環境設定 引言 在現在的科技環境裡,程式設計已經是一項重要技能。無論你是對資料科學有興趣、想成為開發者,或是想踏入人工智慧(AI)領域,學會寫程式都能明顯提升你的競爭力。在眾多程式語言中,Python 因為語法簡單、功能強大、應用範圍廣泛,成為許多人進入程式世界的第一選擇。這篇文章會帶你認識 Python 的背景與優勢,並一步步教你在不同系統上安裝與設定 Python 開發環境,最後寫出第一支 Python 程式。 為什麼選擇 Python? Python 是一種高階程式語言,由 Guido van Rossum 在 1991 年發布。Python 的設計哲學強調程式碼的可讀性,並用縮排來定義程式區塊,這點和許多使用大括號的語言不同。簡潔的語法讓它成為初學者的理想選擇;就算是經驗豐富的開發者,也能用它完成複雜的專案。 Python 的優勢如下: 簡單易學 :Python 的語法清楚、結構簡潔,初學者很快就能上手。和其他語言相比,學習曲線相對平緩,不需要先弄懂一堆複雜觀念,就能開始寫程式。 應用範圍廣泛 :從資料科學、網頁開發、人工智慧、機器學習、自動化測試到網路爬蟲,Python 都有大量開源函式庫與工具支援,而且在這些領域都扮演關鍵角色。 豐富的函式庫與框架 :Python 的函式庫生態系非常龐大。做資料分析有 NumPy、Pandas;開發網站有 Django、Flask;做深度學習有 TensorFlow、PyTorch。各種需求幾乎都能找到對應的套件,讓開發更有效率。 跨平台支援 :Python 支援 Windows、macOS、Linux 等作業系統,程式通常不需要太多修改就能跨平台執行,讓開發與部署更有彈性。 活躍的社群 :Python 擁有龐大的開發者社群。學習或開發上遇到問題,幾乎都能在社群與論壇(例如 Stack Overflow)找到答案,對初學者來說是很強的後盾,也能減少卡關時的挫折感。 Python 的應用領域 Python 的流行與強大功能,讓許多領域都開始大量使用它。以下是幾個常見的應用方向: 資料科學 :隨著大數據與人工智慧興起,資料科學大量使用 Python。NumPy、Pandas 與 Matplotlib 等工具能處理和分析龐...

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門 隨著人工智慧(AI)與深度學習(Deep Learning)快速發展,越來越多人對這些技術產生興趣。不論你是想踏入 AI 領域的初學者,還是已經有程式基礎的開發者,學好 Python 與深度學習框架(例如 PyTorch),都能為你打開更多可能。 為什麼選擇 Python? Python 已經是資料科學與人工智慧領域的首選語言。它的語法簡潔、容易上手,而且擁有龐大的生態系與大量開源函式庫。無論是資料處理、資料視覺化,還是建立機器學習與深度學習模型,Python 都能勝任。對想進入 AI 或資料科學領域的人來說,它幾乎是必備工具。 PyTorch 是什麼? PyTorch 是由 Meta(原 Facebook)AI 研究團隊開發的開源深度學習框架,以易用、靈活和動態計算圖著稱,是許多 AI 研究人員與開發者的首選。相較於其他框架,PyTorch 的寫法更貼近原生 Python,對初學者相對友善。無論是簡單的實驗,還是複雜的深度學習模型,PyTorch 都能提供強大的支援。 這個系列能帶給你什麼? 這個系列會從 Python 的基礎開始,帶你一步一步學習,最後能自己用 PyTorch 建立深度學習模型。即使你完全沒有寫過程式,也能跟著文章的節奏累積技能,理解 AI 與深度學習的核心觀念。 本系列涵蓋的主題 Python 基礎:從變數、條件判斷到函式與模組。 資料處理工具:用 NumPy 與 Pandas 有效率地操作資料。 資料視覺化:用 Matplotlib 與 Seaborn 把資料畫成圖表。 深度學習的數學基礎:線性代數、微積分與機率。 PyTorch 入門:理解張量、模型建構與 GPU 加速。 基礎深度學習模型:CNN 與 RNN 的實作應用。 深度學習專案實戰:從資料前處理到模型部署的端到端流程。 誰適合這個系列? 程式初學者 :如果你對 AI 充滿好奇,卻還沒寫過程式,系列的第一部分會帶你快速上手 Python,並幫助你理解深度學習的基本觀念。 資料科學愛好者 :如果你已經熟悉一些資料處理方法,進階部分會教你如何用 PyTorch 建構深度學習模型。 開發者與研究人員 :想更深入了...