Skip to content
Phạm Khánh Minh Mẫn / syllabus

MÔN 02 / Bài 02

Ma trận là phép biến đổi

Nhìn không gian bị quay, kéo, trượt để hiểu phép nhân ma trận.

PDF ghi tay

Bản cô đọng: hình trước, công thức sau. Nền trắng, chữ đen.

Trong bài này ↓

Chữ gạch chấm là tham chiếu tới môn hoặc tài liệu chưa được đưa lên website.

~3-4 giờ · cần xong bài 1 trước · ĐÂY LÀ BÀI QUAN TRỌNG NHẤT CỦA MÔN 2

Trước bài này, ma trận là danh từ — một bảng số. Sau bài này, ma trận là động từ — một hành động lên không gian.

Mọi thứ còn lại của môn 2 (định thức, hạng, eigenvector, SVD) chỉ có nghĩa nếu bạn giữ được cách nhìn đó. Người học sai chỗ này sẽ mãi tính được mà không hiểu được.

🧭 Làm theo thứ tự này

  1. Xem trước: 3Blue1Brown tập 2 Linear combinations, span, and basis vectors và tập 3 Linear transformations and matrices. Tập 3 là tập quan trọng nhất cả series, xem kỹ.
  2. Làm ô ⚡ bên dưới: chạy code, nhìn hai dòng cuối in ra khác nhau.
  3. Đọc §1-4 (kể cả §3b). Ở §3, tự tính tay AB và BA trước khi xem đáp án. Xem tập 4 Matrix multiplication as composition ngay sau §3 (chính là §3 bằng hình động).
  4. Code §5: tự cài matmul, không dùng @. Đọc bẫy §6.3 (chỉ số hàng/cột) trước khi gõ. Tự viết xong mới mở code mẫu trong bài.
  5. Tự kiểm §8.
  6. Sau cùng: xem lại tập 3, rồi đọc lại §2. Nó sẽ đọc khác hẳn.

Xong bài khi: giải thích được vì sao AB ≠ BA bằng hành động, không bằng số.

⚡ 30 phút đầu — làm trước, đọc sau

import numpy as np
R = np.array([[0.,-1.],[1.,0.]])   # quay 90°
S = np.array([[1., 1.],[0.,1.]])   # trượt ngang
i = np.array([1.,0.]); j = np.array([0.,1.])

print(R @ i, R @ j)     # so với hai CỘT của R — thấy gì?
print(S @ (R @ i))      # quay rồi trượt
print(R @ (S @ i))      # trượt rồi quay  → có bằng nhau không?

Thấy hai dòng cuối ra khác nhau → bạn vừa chạm vào lý do AB ≠ BA. Đọc tiếp để hiểu vì sao.


1. Cách nhìn cũ và cách nhìn mới

Bạn quen nhìn ma trận là một lưới số:

M = [ 0  -1 ]
    [ 1   0 ]

Nhìn vậy thì "nhân ma trận" là một quy tắc hàng-nhân-cột phải học thuộc. Vô nghĩa, và quên ngay.

Cách nhìn đúng:

Ma trận = một phép biến đổi toàn bộ không gian. Nó nhận vào một vector, trả ra một vector khác — nghĩa là nó di chuyển mọi điểm trong không gian.

Ma trận M ở trên là phép quay 90° ngược chiều kim đồng hồ. Không phải "lưới số có số 0 và −1" — mà là một cú xoay.

Nhìn bằng mắt, phép biến đổi tuyến tính có ba tính chất: đường thẳng vẫn thẳng sau khi biến đổi, gốc toạ độ đứng yên, và lưới ô vuông đều biến thành lưới song song, cách đều (các đường song song vẫn song song, các ô vẫn đều nhau). Chỉ vậy. Kéo giãn, nén, quay, lật, bóp dẹp — tất cả đều hợp lệ. (Bài 4 dùng tính chất thứ ba để giải thích vì sao định thức chỉ cần MỘT con số cho cả không gian. §2 bên dưới nói cùng ý đó bằng đại số: tôn trọng phép cộng và phép nhân vô hướng.)


2. Chìa khoá: CỘT của ma trận = nơi vector cơ sở đáp xuống

Đây là ý tưởng làm sập cả bức tường.

Gọi î = (1,0) và ĵ = (0,1) — hai vector cơ sở, đơn vị trên hai trục.

Cột thứ nhất của ma trận = nơi î đáp xuống. Cột thứ hai = nơi ĵ đáp xuống. Hết.

Kiểm bằng số, hai ma trận sẽ dùng suốt bài:

R = [ 0  -1 ]   ← quay 90°          S = [ 1  1 ]   ← trượt ngang (shear)
    [ 1   0 ]                           [ 0  1 ]
î=(1,0) bay tới ĵ=(0,1) bay tới Cột của ma trận
R (0, 1) (−1, 0) (0,1) và (−1,0) ✓ trùng khớp
S (1, 0) (đứng yên) (1, 1) (trượt sang phải) (1,0) và (1,1) ✓ trùng khớp

Vì sao trùng khớp? Tự chứng minh trong 2 dòng: nhân M với (1,0) thì mọi số hạng có ĵ đều nhân với 0 — chỉ còn cột 1. Tương tự với (0,1) chỉ còn cột 2.

Hệ quả cực mạnh

Biết î và ĵ đi đâu là biết toàn bộ phép biến đổi, vì mọi vector khác đều là tổ hợp của chúng:

v = (3, 2) = 3î + 2ĵ
→ M·v = 3·(nơi î đáp) + 2·(nơi ĵ đáp)

Đó chính là ý nghĩa của chữ "tuyến tính": phép biến đổi tôn trọng phép cộng và phép nhân vô hướng. Bạn không cần biết nó làm gì với vô hạn điểm — chỉ cần biết nó làm gì với hai vector.

Ma trận 2×2 chỉ có 4 số, nhưng mô tả trọn một hành động lên vô hạn điểm của mặt phẳng. Đó là toàn bộ sức mạnh của đại số tuyến tính, nén trong một câu.


3. Nhân ma trận = LÀM LIÊN TIẾP hai phép biến đổi

Không phải quy tắc tính toán. Nó là ghép hành động.

S · R nghĩa là: làm R trước, rồi làm S. (Đọc từ phải sang trái — giống f(g(x)).)

Ví dụ tính tay — và đây là chỗ AB ≠ BA lộ ra

Lấy v = î = (1, 0), đi theo hai thứ tự:

Quay rồi trượt (S·R):

R·(1,0) = (0,1)        quay 90° → chỉ lên trên
S·(0,1) = (1,1)        trượt ngang → lệch sang phải
                       KẾT QUẢ: (1, 1)

Trượt rồi quay (R·S):

S·(1,0) = (1,0)        trượt không đụng tới vector nằm ngang
R·(1,0) = (0,1)        quay 90°
                       KẾT QUẢ: (0, 1)

(1,1) ≠ (0,1). Cùng hai phép biến đổi, khác thứ tự, khác kết quả.

Nhân ra ma trận tích để đối chiếu:

S·R = [ 1  -1 ]        R·S = [ 0  -1 ]
      [ 1   0 ]              [ 1   1 ]

(S·R)·(1,0) = (1,1) ✓ khớp "quay rồi trượt"
(R·S)·(1,0) = (0,1) ✓ khớp "trượt rồi quay"

Vì sao AB ≠ BA? Vì thứ tự hành động quan trọng. Đi tất rồi đi giày, khác hẳn đi giày rồi đi tất. Không có gì bí ẩn — bí ẩn chỉ xuất hiện khi bạn nhìn ma trận là bảng số.

Ngược lại, vì sao (AB)C = A(BC) thì luôn đúng?

Vì cả hai đều là "làm C, rồi B, rồi A". Thứ tự không đổi, chỉ đổi cách gộp nhóm. Tính kết hợp là hiển nhiên khi nhìn bằng hành động — và là một định lý phải chứng minh khi nhìn bằng bảng số.


3b. Cây cầu về bài 1: phần tử (i, j) của tích là một tích vô hướng

Bạn đã có hai cách hiểu nhân ma trận: làm liên tiếp hai hành động (§3) và quy tắc tính từng ô. Quy tắc từng ô, nói bằng bài 1, rất ngắn:

Phần tử (i, j) của A·B = tích vô hướng của HÀNG i của A với CỘT j của B.

A = [ 1  2 ]    B = [ 5  6 ]    A·B = [ 19  22 ]
    [ 3  4 ]        [ 7  8 ]          [ 43  50 ]

(A·B)[0,1] = hàng 0 của A · cột 1 của B = (1,2)·(6,8) = 1×6 + 2×8 = 22 ✓

Chuyển vị Aᵀ = đổi hàng thành cột (hàng i của A thành cột i của Aᵀ):

A = [ 1  2 ]      Aᵀ = [ 1  3 ]
    [ 3  4 ]           [ 2  4 ]

Hai ý trên ghép lại cho ra thứ bạn sẽ gặp trong mọi paper về attention. Cho Q là bảng truy vấn (mỗi hàng là một token) và K là bảng khoá (mỗi hàng một token), cùng d chiều. Thì Q·Kᵀ có kích thước n × n, và:

`(Q·Kᵀ)[i, j] = (hàng i của Q) · (hàng j của K) = tích vô hướng của truy vấn i với khoá j. Cả bảng là mọi cặp tích vô hướng giữa truy vấn và khoá. Theo bài 1, mỗi ô đo "token i hỏi gần với khoá của token j đến mức nào".

Q = [ 1  0 ]    K = [ 2  0 ]    Q·Kᵀ = [ 2  0  1 ]    ← hàng 0: truy vấn 0 với khoá 0, 1, 2
    [ 0  1 ]        [ 0  3 ]           [ 0  3  1 ]
    [ 1  1 ]        [ 1  1 ]           [ 2  3  2 ]

Bài 2 gọi quy tắc hàng·cột là "vô nghĩa" khi học thuộc. Nó chỉ trở nên có nghĩa khi bạn thấy mỗi ô là một phép đo góc của bài 1.


4. Phần thưởng: vì sao mạng nơ-ron BẮT BUỘC cần hàm phi tuyến

Đây là kết quả lớn nhất bạn lấy được từ bài 2, và nó trả cổ tức tận môn 7.

Giả sử một mạng nơ-ron chỉ gồm các phép nhân ma trận chồng lên nhau:

đầu ra = W₃ · (W₂ · (W₁ · x))

Nhưng nhân ma trận có tính kết hợp, nên:

W₃ · (W₂ · (W₁ · x)) = (W₃ · W₂ · W₁) · x = W · x

Ba lớp gộp lại thành đúng MỘT ma trận. Kiểm bằng số (ma trận ngẫu nhiên 2×2):

từng lớp một  : [-1.8602582  -0.09157208]
gộp 1 ma trận : [-1.8602582  -0.09157208]
lệch tối đa   : 2.22e-16      ← sai số làm tròn máy tính, tức bằng nhau

→ Xếp 100 lớp tuyến tính vẫn chỉ mạnh bằng 1 lớp. Sâu bao nhiêu cũng vô ích.

Đó là lý do giữa các lớp bắt buộc phải chèn một hàm phi tuyến (ReLU, GELU...): để phá tính kết hợp, khiến các lớp không gộp được — và chiều sâu mới có ý nghĩa.

Bạn vừa tự chứng minh một trong những sự thật nền tảng nhất của deep learning, bằng đúng phép nhân ma trận vừa học.


4b. ⭐ Kết hợp cho cùng KẾT QUẢ, không cho cùng GIÁ — gốc của linear attention (bổ sung từ VMLS — 2026-10)

(nguồn: VMLS tr.182-183, §10.1 (abᵀc, tích ba ma trận); tr.198, bt 10.44)

§3 đã chứng minh (AB)C = A(BC). Câu chưa hỏi: hai vế tốn bao nhiêu? Với A: m×n, B: n×p, C: p×q, một tích m×n nhân n×p tốn khoảng 2mnp flop, nên:

(AB)C : 2mnp + 2mpq  = 2mp(n+q)        A(BC) : 2npq + 2mnq = 2nq(m+p)

Hai số này không bằng nhau. Ví dụ sách dùng là a bᵀ c với a, b, c là n-vector: (abᵀ)c dựng ma trận n×n rồi nhân (~3n² flop, n² số nhớ), còn a(bᵀc) tính một tích vô hướng rồi nhân số (~3n flop, một số nhớ). Với n = 2000: trung gian 32 MB so với 16 KB, cùng đáp số.

Cùng thủ thuật cho attention bỏ softmax: Q, K, V đều N×d. (QKᵀ)V dựng ma trận N×N (4N²d flop); Q(KᵀV) chỉ dựng ma trận d×d (4Nd² flop). Tỉ lệ đúng bằng N/d: với N = 4096, d = 64 là 64 lần flop, và N×N float64 là 134 MB so với 32 KB. Kết quả hai đường lệch nhau cỡ 5e−15 (sai số làm tròn). Thời gian đo trên máy này: cỡ 13 ms so với 0.17 ms, phụ thuộc máy (BLAS, bộ nhớ), nhưng thứ tự lớn thì không đổi.

Vì sao attention thật không làm được vậy: softmax(QKᵀ)V có hàm phi tuyến nằm giữa hai phép nhân, nên không đổi chỗ được. Dòng linear attention thay softmax bằng một ánh xạ đặc trưng φ để lấy lại quyền đổi thứ tự: φ(Q)(φ(K)ᵀV), chi phí theo N chỉ còn tuyến tính. Xem môn 8 bài 5 (Bảng 1: vì sao O(N²) đáng ngại) và bài 9 (cách nhìn hạng thấp của ma trận attention).

import numpy as np, time
rng = np.random.default_rng(0)
n = 2000; a, b, c = rng.normal(size=(3, n))
M = np.outer(a, b); x1, x2 = M @ c, a * (b @ c)
assert np.allclose(x1, x2) and M.nbytes == 32_000_000 and x2.nbytes == 16_000     # cùng kết quả, khác giá

N, d = 4096, 64
Q, K, V = rng.normal(size=(3, N, d))
S = Q @ K.T; A, B = S @ V, Q @ (K.T @ V)                 # trung gian N×N  vs  d×d
assert np.abs(A - B).max() / np.abs(A).max() < 1e-12
assert (4*N*N*d) / (4*N*d*d) == N / d == 64              # tỉ lệ flop lý thuyết
assert S.nbytes == 8 * N * N and (K.T @ V).nbytes == 8 * d * d

def do(f, r=3):                                          # thời gian nhỏ nhất của r lần chạy
    best = 1e9
    for _ in range(r):
        s = time.perf_counter(); f(); best = min(best, time.perf_counter() - s)
    return best
print(round(do(lambda: (Q @ K.T) @ V), 4), round(do(lambda: Q @ (K.T @ V)), 5))  # giây, phụ thuộc máy

5. Code — tự cài matmul, KHÔNG dùng @

import numpy as np

def matmul(A, B):
    """Nhân ma trận tự cài. Chậm hơn numpy ~100 lần — mục đích là HIỂU."""
    n, k  = A.shape
    k2, m = B.shape
    assert k == k2, f"chiều không khớp: {A.shape} × {B.shape}"
    C = np.zeros((n, m))
    for i in range(n):
        for j in range(m):
            for t in range(k):
                C[i, j] += A[i, t] * B[t, j]
    return C


R = np.array([[0., -1.], [1., 0.]])
S = np.array([[1.,  1.], [0., 1.]])

# (a) CỘT = nơi vector cơ sở đáp xuống
i, j = np.array([1., 0.]), np.array([0., 1.])
assert np.allclose(R @ i, R[:, 0]) and np.allclose(R @ j, R[:, 1])
print("cột = ảnh của vector cơ sở ✓")

# (b) matmul tự cài phải khớp numpy
assert np.allclose(matmul(S, R), S @ R)
print("matmul tự cài khớp numpy ✓")

# (c) AB ≠ BA
print("S@R =\n", S @ R, "\nR@S =\n", R @ S)
assert not np.allclose(S @ R, R @ S)

# (d) ba lớp tuyến tính = một lớp
rng = np.random.default_rng(0)
W1, W2, W3 = (rng.normal(size=(2, 2)) for _ in range(3))
x = np.array([1.7, -0.4])
assert np.allclose(W3 @ (W2 @ (W1 @ x)), (W3 @ W2 @ W1) @ x)
print("3 lớp tuyến tính = 1 lớp ✓  → đây là lý do cần phi tuyến")

# (e) ma trận đơn vị giao hoán với TẤT CẢ
I = np.eye(2)
assert np.allclose(I @ R, R) and np.allclose(R @ I, R)

# (f) 3x3 — quy tắc "cột = ảnh cơ sở" không đổi
Rz = np.array([[0., -1., 0.], [1., 0., 0.], [0., 0., 1.]])
for t, e in enumerate(np.eye(3)):
    assert np.allclose(Rz @ e, Rz[:, t])
assert np.allclose(np.linalg.matrix_power(Rz, 4), np.eye(3))   # quay 4 lần = về chỗ cũ

# (g) BẪY §6.3 — sai một chỉ số ra đúng A@B.T, KHÔNG crash
A2 = np.array([[1., 2.], [3., 4.]]); B2 = np.array([[5., 6.], [7., 8.]])
def matmul_sai(A, B):
    C = np.zeros((2, 2))
    for i in range(2):
        for j in range(2):
            for t in range(2):
                C[i, j] += A[i, t] * B[j, t]      # B[j,t] — SAI
    return C
assert np.allclose(matmul_sai(A2, B2), A2 @ B2.T)   # sai lặng lẽ, ra tích với chuyển vị
assert not np.allclose(matmul_sai(A2, B2), A2 @ B2)
print("bẫy chỉ số: sai lặng lẽ ra A@B.T ✓  → chỉ assert mới bắt được")

Quy tắc 1 đang được luyện ở đây: khi matmul tự cài lệch numpy, nguyên nhân gần như luôn là chỉ số vòng lặp hoặc chiều ma trận — không phải hiểu sai toán. Ghi vào nhật ký lỗi.


6. Ba thứ phải biết trước khi sang bài 3

6.1. Ma trận đơn vị I — phép biến đổi "không làm gì"

I = [ 1  0 ]     î → (1,0)   ĵ → (0,1)     mọi vector đứng yên
    [ 0  1 ]

Cột của I chính là î và ĵ — đúng chỗ chúng vốn đã ở. Nó là phần tử trung hoà:

I·R = R·I = R     ✓ kiểm bằng số, đúng với MỌI R

Đây là ngoại lệ duy nhất của AB ≠ BA mà bạn cần nhớ: I giao hoán với tất cả, vì "không làm gì" thì làm trước hay sau cũng như nhau. Ẩn dụ backend: I là no-op middleware.

I sẽ là định nghĩa của ma trận nghịch đảo ở bài 4: A⁻¹ là ma trận mà A⁻¹A = I — tức phép biến đổi đưa mọi thứ về đúng chỗ cũ.

6.2. Ma trận 3×3 — mọi thứ vẫn đúng, chỉ thêm một cột

Quay 90° quanh trục z trong không gian 3 chiều:

Rz = [ 0  -1   0 ]      î  → ( 0, 1, 0)     ← cột 1
     [ 1   0   0 ]      ĵ  → (−1, 0, 0)     ← cột 2
     [ 0   0   1 ]      k̂  → ( 0, 0, 1)     ← cột 3 (trục z đứng yên)

Quy tắc "cột = nơi vector cơ sở đáp xuống" không đổi một chữ. Ma trận n×n chỉ là "tôi cho bạn biết n vector cơ sở bay đi đâu".

Kiểm bằng số: quay 90° bốn lần thì về chỗ cũ → Rz⁴ = I ✓

6.3. 🪤 BẪY — chỉ số hàng/cột, lỗi kinh điển nhất khi tự cài matmul

Công thức đúng: C[i,j] += A[i,t] * B[t,j]

Viết nhầm B[j,t] thay B[t,j] — một ký tự — và code vẫn chạy, vẫn ra ma trận 2×2, không báo lỗi:

A = [1 2]   B = [5 6]
    [3 4]       [7 8]

ĐÚNG  A@B    = [19 22]        SAI  B[j,t]  = [17 23]
                [43 50]                        [39 53]

Kết quả sai đó không phải rác — nó chính xác bằng A @ B.T. Bạn vô tình tính tích với ma trận chuyển vị. Loại lỗi này không bao giờ crash, chỉ âm thầm cho số sai.

Đây là quy tắc 1 ở dạng nhỏ nhất, sờ được: lỗi giết bạn là chi tiết thiết lập, không phải toán. Bạn hiểu đúng 100% về phép biến đổi, và vẫn sai vì một chỉ số.

Cách chặn duy nhất: assert np.allclose(matmul(A,B), A @ B). Không có cách nào khác — đọc lại code bằng mắt sẽ không bắt được.

Nếu bạn vừa dính bẫy này: đó là dòng đầu tiên đáng ghi vào nhật ký lỗi.

6.4. Bảng công thức — mỗi dòng kèm nghĩa "phép biến đổi" (bổ sung 2026-10)

Phép Công thức Nghĩa khi nhìn ma trận là phép biến đổi
Cộng (A+B)[i,j] = A[i,j] + B[i,j] · A+B = B+A (A+B)·v = A·v + B·v: áp hai phép riêng rồi cộng kết quả
Nhân với số (c·A)[i,j] = c·A[i,j] (c·A)·v = c·(A·v): co/giãn kết quả c lần; c < 0 thì lật hướng
Nhân ma trận (A·B)[i,j] = Σₜ A[i,t]·B[t,j] · cỡ (m×n)·(n×p) = m×p Làm B trước rồi A; hai số giữa phải bằng nhau (đầu ra của B vừa đầu vào của A)
Kết hợp (AB)C = A(BC) — luôn đúng Cùng thứ tự "C, rồi B, rồi A", chỉ đổi cách gộp (§3)
Phân phối A(B+C) = AB + AC — luôn đúng
Giao hoán AB ≠ BA nói chung · IA = AI = A Đổi thứ tự hành động là đổi kết quả; I = không làm gì (§6.1)
Chuyển vị Aᵀ[i,j] = A[j,i] · (Aᵀ)ᵀ = A · (A+B)ᵀ = Aᵀ+Bᵀ Lật qua đường chéo chính; cỡ m×n thành n×m
Chuyển vị của tích (AB)ᵀ = BᵀAᵀ — ĐẢO thứ tự Như cởi đồ: mặc tất rồi giày thì cởi giày rồi tất
Tích vô hướng a·b = aᵀb Bài 1 viết thành một phép nhân ma trận (1×n)·(n×1)
Phép quay Rᵀ = R⁻¹ Chuyển vị = quay ngược lại (ma trận trực giao, bài 6)
Nghịch đảo A⁻¹A = I · (AB)⁻¹ = B⁻¹A⁻¹ — ĐẢO thứ tự Làm ngược lại; công thức 2×2 và khi nào không có A⁻¹: bài 4

Hai dòng đảo thứ tự cùng một lý do: muốn gỡ một chuỗi hành động thì gỡ cái làm sau cùng trước.

import numpy as np
A = np.array([[1., 2.], [3., 4.]]); B = np.array([[5., 6.], [7., 8.]]); C = np.array([[0., 1.], [2., 3.]])
v, c, I = np.array([3., 2.]), 2.0, np.eye(2)
R = np.array([[0., -1.], [1., 0.]])
assert np.allclose((A + B) @ v, A @ v + B @ v) and np.allclose((c * A) @ v, c * (A @ v))
assert np.allclose((A @ B) @ C, A @ (B @ C)) and np.allclose(A @ (B + C), A @ B + A @ C)
assert np.allclose((A @ B).T, B.T @ A.T) and not np.allclose((A @ B).T, A.T @ B.T)   # giữ thứ tự là SAI
assert np.allclose(R.T @ R, I)                                                        # Rᵀ = R⁻¹
assert np.allclose(np.linalg.inv(A @ B), np.linalg.inv(B) @ np.linalg.inv(A))
assert not np.allclose(A * B, A @ B)          # BẪY: * là nhân TỪNG Ô ([[5,12],[21,32]]), @ mới là nhân ma trận
print("bảng công thức ✓")

7. Nối vào AI

Chỗ trong AI Là phép biến đổi gì
Một lớp mạng nơ-ron W·x Biến đổi không gian biểu diễn
Q = X·W^Q, K = X·W^K trong attention Chiếu token sang "không gian truy vấn" và "không gian khoá" — rồi mới lấy tích vô hướng (bài 1)
Embedding Ma trận không vuông: biến đổi từ không gian 100k chiều từ vựng xuống ~768 chiều
Xếp nhiều lớp Ghép phép biến đổi — và §4 giải thích vì sao phải chèn phi tuyến vào giữa

Chú ý điểm nối: bài 1 dạy tích vô hướng đo góc. Bài 2 dạy ma trận biến đổi không gian. Attention làm cả hai: W^Q và W^K biến đổi trước, rồi QKᵀ đo góc sau.


8. Tự kiểm — trả lời được mới sang bài 3

  1. Vì sao chỉ cần biết î và ĵ đáp xuống đâu là biết trọn phép biến đổi? Nhắc tới hai tính chất đại số của "tuyến tính" (§2: tôn trọng phép cộng, tôn trọng phép nhân vô hướng).
  2. AB ≠ BA — giải thích bằng hành động, không bằng ví dụ số.
  3. Nhưng (AB)C = A(BC) thì luôn đúng. Vì sao thứ tự bị cấm đổi mà cách gộp nhóm thì không?
  4. Ma trận đơn vị I = [[1,0],[0,1]] làm gì với không gian? Vì sao IA = AI = A dù nói chung AB ≠ BA?
  5. Một ma trận bóp dẹp cả mặt phẳng thành một đường thẳng. Hai cột của nó có quan hệ gì với nhau? (Đây là cửa vào khái niệm hạng ở bài 3.)
  6. Chứng minh bằng nhân ma trận rằng 3 lớp tuyến tính chồng nhau = 1 lớp. Suy ra vì sao mạng nơ-ron bắt buộc cần phi tuyến.
  7. Ma trận 3×2 biến đổi từ không gian nào sang không gian nào? Còn 2×3? (Cửa vào embedding.)
  8. Q có 3 hàng, K có 3 hàng, mỗi hàng 2 chiều. Q·Kᵀ có kích thước bao nhiêu, và ô (i, j) của nó đo cái gì? (Dùng §3b.)

Câu 5 và 6 là hai câu đáng nhất. Câu 6 bạn đã tự chứng minh bằng code ở §5 — giờ nói lại bằng lời.


9. Bài tập về nhà trước bài 3

3Blue1Brown — Essence of Linear Algebra:

Tập Vì sao
2 — Linear combinations, span, and basis vectors Xem trước, nó dựng nền cho tập 3
3 — Linear transformations and matrices ⭐ XEM HAI LẦN. Tập bản lề của cả series
4 — Matrix multiplication as composition Chính là §3 của bài này, bằng hình động

Xem xong tập 3, quay lại đọc §2 của bài này một lần nữa. Nó sẽ đọc khác hẳn.

Bài 3 sẽ là: span, hạng, không gian cột — trả lời câu 5 ở trên, và là nền cho low-rank / SVD / LoRA.

Vị trí đọc được lưu trên trình duyệt này khi cho phép lưu trữ; không đồng bộ giữa các thiết bị.