Mỗi học sinh trong bảng điểm được mô tả bằng ba con số: giờ tự học mỗi tuần, điểm học kỳ 1 và số buổi vắng. Bốn trăm học sinh là một bảng 400 dòng, 3 cột. Một model tuyến tính dự đoán điểm cuối kỳ cho cả 400 học sinh bằng một phép nhân, viết trong NumPy là X @ w; một lớp của mạng neural cũng là một phép nhân như thế. Bài 0.2 đã dùng @; bài này giải thích nó tính gì: vector là gì, tích vô hướng đo gì, và vì sao số cột của ma trận bên trái phải bằng số hàng của ma trận bên phải.
Vector: một dãy số có thứ tự
Một vector là một dãy số có thứ tự. Học sinh A tự học 6 giờ, điểm học kỳ 1 là 7.5, vắng 1 buổi, nên được mô tả bằng vector . Thứ tự quan trọng: là một học sinh khác. Số phần tử của vector gọi là số chiều. Mỗi con số mô tả một mẫu dữ liệu, như giờ tự học hay số buổi vắng, gọi là một đặc trưng (feature); mỗi đặc trưng là một chiều.
Vector hai chiều vẽ được thành một mũi tên từ gốc tọa độ tới điểm . Hai phép tính cơ bản đều làm từng phần tử:
Cộng hai vector là nối mũi tên này vào đầu mũi tên kia. Nhân với số là kéo dài mũi tên lần, hoặc đảo chiều khi .
import numpy as np
a = np.array([3.0, 1.0])
b = np.array([1.0, 2.0])
print(a + b, 2 * a, a - b)
[4. 3.] [6. 2.] [ 2. -1.]
Phép trừ cho mũi tên đi từ đầu tới đầu . Mục sau dùng nó để đo khoảng cách.
Hỏi nhanh
và . bằng bao nhiêu?
, cộng được . là quên nhân 2. là nhân 2 rồi bỏ dấu trừ. là trừ thay vì cộng.
Độ dài và khoảng cách
Độ dài của vector là cạnh huyền của tam giác vuông có hai cạnh 3 và 4, bằng 5 theo định lý Pythagoras. Tổng quát cho chiều, độ dài, hay chuẩn L2 (L2 norm), là
Khoảng cách giữa hai điểm là độ dài của hiệu: . Đây là khoảng cách Euclid, cách đo mà kNN ở bài 2.4 dùng để tìm hàng xóm gần nhất.
Còn một cách đo khác: cộng trị tuyệt đối từng thành phần, , gọi là chuẩn L1. Trên bàn cờ, xe đi theo hàng và cột, nên quãng đường của nó là khoảng cách L1, còn quãng đường chim bay là khoảng cách L2.
p = np.array([1.0, 2.0])
q = np.array([4.0, 6.0])
d = q - p
print(d, np.linalg.norm(d), np.sqrt((d ** 2).sum()), np.abs(d).sum())
[3. 4.] 5.0 5.0 7.0
Từ tới phải đi 3 theo trục ngang và 4 theo trục dọc. Đường thẳng dài 5, đường đi theo ô dài 7. np.linalg.norm mặc định tính chuẩn L2, đúng bằng công thức viết tay.
Hỏi nhanh
Vector có độ dài L2 bằng bao nhiêu?
. là tổng trị tuyệt đối, tức chuẩn L1. là quên lấy căn. là chỉ tính hai thành phần đầu.
Tích vô hướng
Tích vô hướng (dot product) của hai vector cùng số chiều là tổng các tích từng cặp:
Kết quả là một số, không phải vector. Ý nghĩa đầu tiên là tổng có trọng số. Ở bài 0.4, hàm bậc nhất chỉ có một đầu vào. Với ba đặc trưng, model tuyến tính tính
Mỗi trọng số nói đặc trưng thứ đóng góp bao nhiêu. Trọng số âm cho số buổi vắng nghĩa là vắng càng nhiều thì điểm dự đoán càng thấp.
Ý nghĩa thứ hai là hình học. Gọi là góc giữa hai mũi tên, khi đó
Không cần nhớ lượng giác để đọc công thức này. bằng 1 khi hai mũi tên cùng hướng, bằng 0 khi chúng vuông góc, bằng khi ngược hướng. Vì vậy dấu của tích vô hướng cho biết hai vector “cùng phía” hay “ngược phía”.
Chia tích vô hướng cho hai độ dài, ta còn lại đúng , gọi là cosine similarity. Nó chỉ đo hướng, không đo độ dài, nên nằm trong khoảng từ đến 1. Các chương sau biểu diễn một từ hay một ảnh bằng vector, gọi là embedding, rồi dùng cosine similarity để tìm từ hay ảnh giống nhau.
w = np.array([0.1, 0.8, -0.3]) # giờ tự học, điểm HK1, số buổi vắng
x = np.array([6.0, 7.5, 1.0]) # học sinh A
print(w @ x, (w * x).sum(), w @ x + 1.0)
def cosine(u, v):
return u @ v / (np.linalg.norm(u) * np.linalg.norm(v))
meo = np.array([0.9, 0.8, 0.1])
cho = np.array([0.8, 0.9, 0.2])
oto = np.array([0.1, 0.2, 0.9])
print(round(cosine(meo, cho), 3), round(cosine(meo, oto), 3))
6.3 6.3 7.3
0.99 0.303
Dòng đầu: tích vô hướng bằng tổng các tích từng cặp, ; cộng thêm được điểm dự đoán 7.3. Dòng hai dùng ba vector đồ chơi cho ba từ: “mèo” và “chó” gần cùng hướng nên cosine gần 1, “mèo” và “ô tô” lệch hướng nhiều nên cosine chỉ 0.3.
Hỏi nhanh
và . Tích vô hướng bằng bao nhiêu, và hai vector nằm thế nào với nhau?
, nên , hai vector vuông góc. là nhân từng phần tử mà quên cộng lại; tích vô hướng là một số. và là cộng nhầm dấu một trong hai tích.
Ma trận: một bảng số
Xếp vector của bốn học sinh thành bốn hàng, ta được một ma trận 4 hàng, 3 cột, viết là ma trận hay shape (4, 3). Quy ước của học máy: mỗi hàng là một mẫu, mỗi cột là một đặc trưng. Ma trận dữ liệu thường ký hiệu , shape với mẫu và đặc trưng.
Nhân ma trận với vector trọng số là làm tích vô hướng của từng hàng với :
Một phép nhân cho dự đoán của cả học sinh. Mỗi hàng có 3 số và có 3 số, nên số cột của phải bằng độ dài của . Kết quả có số, một số cho mỗi hàng.
X = np.array([[6.0, 7.5, 1.0],
[2.0, 6.0, 4.0],
[10.0, 8.5, 0.0],
[4.0, 5.5, 2.0]])
b = 1.0
print(X.shape, w.shape, (X @ w).shape)
print(X @ w + b)
print([round(float(row @ w + b), 1) for row in X])
(4, 3) (3,) (4,)
[7.3 4.8 8.8 5.2]
[7.3, 4.8, 8.8, 5.2]
Dòng cuối tính lại bằng vòng lặp qua từng hàng và ra đúng bốn số. Phép X @ w làm cùng việc ấy, chỉ nhanh hơn nhiều khi bảng có hàng triệu dòng. Số b được cộng vào cả bốn dự đoán nhờ broadcasting của bài 0.2.
Hỏi nhanh
Bảng dữ liệu có 500 học sinh, mỗi học sinh 8 đặc trưng. Vector trọng số phải có shape gì, và X @ w có shape gì?
Mỗi hàng của X có 8 số, nên w cần 8 trọng số, mỗi đặc trưng một trọng số. Kết quả có một dự đoán cho mỗi học sinh, tức 500 số. w dài 500 là nhầm trọng số theo mẫu với trọng số theo đặc trưng. w shape (500, 8) là một ma trận chứ không phải vector, và (500, 8) @ (500, 8) không nhân được.
Nhân hai ma trận
Giờ muốn hai dự đoán cho mỗi học sinh, chẳng hạn điểm Toán và điểm Văn. Mỗi môn có một vector trọng số riêng. Xếp hai vector ấy thành hai cột của ma trận shape . Khi đó có shape : ô ở hàng , cột là tích vô hướng của hàng của với cột của .
Quy tắc shape:
Hai số ở giữa phải bằng nhau, vì đó là độ dài của hai vector đem nhân vô hướng. Hai số ở ngoài cho shape kết quả. Một lớp của mạng neural làm đúng phép này: là , là , kết quả là đặc trưng mới cho mỗi mẫu. Mỗi cột của là một nơ-ron.
Chuyển vị (trong NumPy là X.T) đổi hàng thành cột, nên shape thành . Thứ tự nhân quan trọng: và nói chung khác nhau, và nhiều khi một trong hai còn không nhân được vì shape không khớp. Ma trận đơn vị có 1 trên đường chéo, 0 ở mọi ô khác; nhân với không đổi gì, như nhân một số với 1.
W = np.array([[0.1, -0.2],
[0.8, 0.5],
[-0.3, 0.4]])
H = X @ W
print(H.shape)
print(np.round(H, 2))
print(X.T.shape, W.T.shape)
try:
W @ X
except ValueError as e:
print("W @ X lỗi:", e)
I = np.eye(3)
print(np.allclose(X @ I, X))
(4, 2)
[[6.3 2.95]
[3.8 4.2 ]
[7.8 2.25]
[4.2 2.75]]
(3, 4) (2, 3)
W @ X lỗi: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 4 is different from 2)
True
Cột đầu của H là X @ w ở mục trước, chưa cộng , vì cột đầu của W chính là w. W @ X là : số 2 và số 4 ở giữa không bằng nhau, nên NumPy báo lỗi. Thông báo lỗi dài nhưng đọc được ý chính ở cuối: kích thước 4 khác 2.
Hỏi nhanh
Nhân ma trận với ma trận cho kết quả gì?
Số cột bên trái bằng số hàng bên phải, cùng là 2, nên nhân được; kết quả lấy số hàng bên trái và số cột bên phải. là lấy hai số ở giữa, đúng những số bị “triệt tiêu”. Hai ma trận không cần cùng shape, chỉ cần khớp số ở giữa.
Ma trận như một phép biến đổi
Một ma trận nhân với mọi điểm của mặt phẳng là một cách biến đổi mặt phẳng. kéo giãn trục ngang gấp đôi. xoay mọi điểm 90 độ ngược chiều kim đồng hồ. Cột đầu của ma trận là nơi điểm đi tới, cột sau là nơi điểm đi tới.
Một lớp của mạng neural cũng làm việc này: nó biến đổi dữ liệu sang một hệ tọa độ mới, nơi các lớp dễ tách nhau hơn.
Trong toán, điểm được viết thành cột và nhân bên phải ma trận: . Trong code, mỗi điểm là một hàng của bảng , nên cùng phép biến đổi ấy viết là X @ M.T.
square = np.array([[0, 0], [1, 0], [1, 1], [0, 1]], dtype=float) # mỗi hàng một đỉnh
M = np.array([[2.0, 1.0],
[0.0, 1.0]])
print(square @ M.T)
[[0. 0.]
[2. 0.]
[3. 1.]
[1. 1.]]
Đỉnh đi tới , đúng cột đầu của ; đỉnh đi tới , đúng cột sau. Hình vuông thành hình bình hành.
Hỏi nhanh
Ma trận xoay điểm 90 độ. Điểm đi tới đâu?
với lấy đúng cột đầu của , tức . là đọc hàng đầu thay vì cột đầu. là xoay 180 độ. Điểm trên trục vẫn bị xoay như mọi điểm khác.
Khi đi thi
- Ghi shape cạnh mỗi biến trước khi nhân. Nhân không được thì xem hai số ở giữa.
@là nhân ma trận,*là nhân từng phần tử.- Kiểm
X @ wbằng một hàng: tínhX[0] @ wrồi so với phần tử đầu.
Tóm tắt
- Vector là dãy số có thứ tự; cộng và nhân với số làm từng phần tử.
- Độ dài L2 , L1 ; khoảng cách là độ dài của hiệu.
- Tích vô hướng là một số: tổng có trọng số, và ; cosine similarity chỉ đo hướng.
- Ma trận dữ liệu : hàng là mẫu, cột là đặc trưng; là tích vô hướng từng hàng với .
- ; chuyển vị đổi thành ; nói chung; nhân với không đổi gì.
- Ma trận biến đổi mặt phẳng; cột của nó là ảnh của hai vector đơn vị.
Kiểm tra cuối bài
Mười câu dưới đây bao quát cả bài. Làm hết rồi xem điểm; câu nào sai thì đọc lại mục tương ứng.
Câu 1
Vector có độ dài Euclid (chuẩn L2) bằng bao nhiêu?
. là chuẩn L1, cộng trị tuyệt đối. là quên lấy căn. là tích hai thành phần, không phải một độ dài.
Câu 2
và là hai ma trận . Phép nào không phải phép toán ma trận thông thường?
Cộng, trừ làm từng ô, nhân ma trận làm tích vô hướng hàng-cột; cả ba đều định nghĩa cho hai ma trận . Không có phép “chia ma trận”. Gần nhất là nhân với ma trận nghịch đảo , và phép này chỉ làm được khi khả nghịch.
Câu 3
Ma trận đơn vị có đặc điểm gì?
Nhờ đường chéo bằng 1 và phần còn lại bằng 0, với mọi nhân được. Ma trận toàn số 1 nhân vào sẽ cộng dồn các cột. Ma trận toàn 0 cho kết quả 0. Đảo vị trí số 0 và số 1 thì nhân vào sẽ làm trộn lẫn các cột với nhau.
Câu 4
Ma trận có shape . có shape gì?
Chuyển vị đổi hàng thành cột, nên 2 hàng 3 cột thành 3 hàng 2 cột. và là shape của và , không phải của .
Câu 5
Trong phép nhân ma trận , kích thước nào phải bằng nhau?
Mỗi ô của là tích vô hướng của một hàng với một cột ; hàng dài bằng số cột của , cột dài bằng số hàng của . Số hàng của và số cột của là shape của kết quả, không cần bằng nhau.
Câu 6
Ma trận nào dưới đây đối xứng, tức là bằng chuyển vị của chính nó?
Đối xứng nghĩa là ô hàng cột bằng ô hàng cột ; ở ma trận , chỉ cần hai ô ngoài đường chéo bằng nhau. Ba ma trận còn lại có hai ô ấy là 2 và 3, 0 và 1, 1 và 0.
Câu 7
Một lớp của mạng neural nhận batch X shape (32, 784) và cho ra (32, 128). Ma trận trọng số W trong X @ W có shape gì?
đòi và . (128, 784) là đúng số nhưng ngược thứ tự; PyTorch lưu trọng số theo shape này rồi nhân với chuyển vị của nó. Hai shape có số 32 là nhầm kích thước batch vào trọng số; trọng số không phụ thuộc số mẫu trong batch.
Câu 8
Hai embedding và có cosine similarity bằng . Nhân đôi thì cosine similarity bằng bao nhiêu?
Nhân đôi làm tích vô hướng và độ dài của cùng gấp đôi, nên tỉ số không đổi. Cosine chỉ đo hướng, và nhân với số dương không đổi hướng. vượt khoảng từ đến 1. chỉ đúng nếu nhân với một số âm.
Câu 9
Bảng có hai cột: tuổi (từ 10 đến 18) và thu nhập gia đình (từ 5 triệu đến 80 triệu đồng mỗi tháng). Dùng khoảng cách Euclid trên dữ liệu thô để tìm học sinh giống nhau thì chuyện gì xảy ra?
Chênh lệch thu nhập có thể tới hàng chục triệu, chênh lệch tuổi chỉ vài năm; bình phương lên càng cách xa. Khoảng cách vẫn tính được, chỉ là bị cột lớn chi phối. Cách sửa là chuẩn hóa từng cột về cùng thang trước khi đo.
Câu 10
A shape (5, 3) và B shape (5, 3). Lệnh nào chạy được?
A.T @ B là , hai số giữa khớp. A @ B và B @ A đều là , số giữa 3 và 5 không khớp. B.T.T chuyển vị hai lần thì quay lại B, nên vẫn là A @ B.
Đọc thêm
- 3Blue1Brown - Essence of linear algebra, tập 1-4 và 9. Vector, tổ hợp tuyến tính, ma trận như phép biến đổi, tích vô hướng, bằng hình động.
- Khan Academy - Vectors and spaces. Bài giảng và bài tập ngắn về vector, độ dài, tích vô hướng.
- Deisenroth, Faisal, Ong - Mathematics for Machine Learning, chương 2 và 3. Sách miễn phí; đọc phần ma trận, chuẩn và tích vô hướng khi muốn chặt chẽ hơn.
- NumPy - Linear algebra (numpy.linalg). Danh sách hàm
norm,matmul,eyevà các phép khác dùng trong bài.