Chuyển đến nội dung chính

Bài 9: PCA không phải là bỏ cột

PCA tạo trục mới từ tổ hợp mọi cột. Không cột nào bị bỏ, và trục mới không có ý nghĩa vật lý.

Xem bản video

Bản video 2:46. Bài viết dưới đây đi sâu hơn và có code chạy được. Cả 13 tập ở playlist, xếp sẵn theo thứ tự 1 → 13.

Cách nghĩ đầu tiên, và vì sao nó sai

Năm cột thì không vẽ lên giấy được. Cách nghĩ đầu tiên: bỏ vài cột ít quan trọng đi.

PCA không làm vậy. Nó tạo ra trục mới bằng tổ hợp của tất cả các cột. Không cột nào bị bỏ, và không trục mới nào còn ý nghĩa vật lý.

Xem loadings của PC1 trên bảng 120 căn hộ, năm cột:

cộttrọng số trong PC1
diện tích+0,567
số phòng+0,557
cách trung tâm−0,112
giá bán+0,574
tầng−0,164

Mọi cột đều góp mặt, kể cả "tầng" với trọng số nhỏ. PC1 không phải "diện tích", cũng không phải "giá" — nó là một trục mới không có tên trong thế giới thật. Bạn không thể nói với đồng nghiệp "PC1 tăng một đơn vị" và mong họ hiểu.

Phương sai là tiêu chí

PCA chọn trục theo phương sai giữ được:

PC1PC2PC3PC4PC5
giữ được58,2%22,4%17,4%2,0%0,0%
tích luỹ58,2%80,6%98,0%100,0%100,0%

Muốn giữ 80% phương sai thì 2 trục là đủ. Muốn 90% hay 95% thì cần 3 trục. Từ 5 chiều xuống 3 chiều mà chỉ mất 2% — vì các cột tương quan mạnh nên chúng vốn đã trùng thông tin nhau.

Phân rã riêng, viết tay

PCA về bản chất là phân rã riêng ma trận hiệp phương sai. Cách viết tay dễ đọc nhất là phép quay Jacobi: mỗi bước chọn một phần tử ngoài đường chéo rồi quay hai trục để triệt tiêu nó.

theta = (a[q][q] - a[p][p]) / (2 * a[p][q])
sign = 1.0 if theta >= 0 else -1.0
t = sign / (abs(theta) + math.sqrt(theta * theta + 1))
c = 1 / math.sqrt(t * t + 1)
s = t * c

Lặp đủ lâu thì mọi phần tử ngoài đường chéo về 0; đường chéo là trị riêng, ma trận quay tích luỹ là véc-tơ riêng. Chậm hơn LAPACK rất nhiều, nhưng đọc được từ trên xuống dưới.

Một chi tiết: véc-tơ riêng chỉ xác định tới một dấu. Không cố định dấu thì cùng dữ liệu có thể in ra hai bảng khác dấu nhau, và người đọc tưởng kết quả không ổn định. Ở đây chọn dấu sao cho thành phần lớn nhất là dương.

Chỗ nó hỏng: quên chuẩn hoá

Bỏ bước chia độ lệch chuẩn, chỉ trừ trung bình:

PC1 giữ 97,9% phương sai, và nó chính là cột diện tích.

Lý do: diện tích tính bằng m² (hàng chục), giá tính bằng tỷ (một chữ số). Phương sai của diện tích lớn hơn phương sai của giá hàng nghìn lần, nên PCA chỉ đi tìm cột nào có đơn vị to nhất. Đây không phải phát hiện gì về dữ liệu — nó là phát hiện về đơn vị đo.

PCA() của sklearn không tự chuẩn hoá. Gọi nó trên dữ liệu thô là một lỗi im lặng.

Chạy thử

Kết quả chạy ep09_pca

Ảnh trên là output thật của python scratch/ep09_pca.py, không phải bảng vẽ lại. Code: scratch/ep09_pca.py · library/ep09_pca.py

PCA khác chọn lọc đặc trưng

Nếu điều bạn cần là bỏ đặc trưng — vì thu thập chúng tốn tiền, hay vì cần giải thích được — thì PCA không làm việc đó. Lasso ở bài 12 mới làm: nó đưa hệ số về đúng 0, tức loại hẳn đặc trưng khỏi mô hình.