Giảm chiều PCA - vector riêng và PC1, PC2

Giảm chiều bằng phân tích thành phần chính: phương sai lớn nhất, PC1 PC2, tỉ lệ giữ lại và hạn chế tuyến tính của PCA.
KhóThuật toán ~60 phút

Giới thiệu

Bài này học PCA để nén nhiều chiều thành 2 trục. Bạn dùng nó để vẽ dữ liệu và chạy mô hình nhanh hơn.

Kiến thức cần nhớ

Vì sao giảm chiều

  • Chiều cao khiến khoảng cách mất ý nghĩa và tính toán nặng.
  • Không vẽ được hình cho người xem ở chiều cao.
  • Giảm xong gom cụm ổn định hơn và chạy nhanh hơn.
  • Ví dụ đời thường: như tóm tắt bảng điểm dài thành 2 con số tổng kết.

Ý tưởng phương sai lớn nhất

  • Hướng dữ liệu trải rộng nhất chứa nhiều thông tin nhất.
  • PC1 là hướng phương sai lớn nhất, PC2 vuông góc và lớn tiếp.
  • Các trục là vector riêng của ma trận hiệp phương sai.
  • Ví dụ đời thường: đám mây xiên thì trục dọc thân mây là PC1.

Tỉ lệ giữ lại

  • Giá trị riêng cho biết lượng phương sai mỗi trục giữ.
  • Tỉ lệ bằng tổng đã chọn chia tổng toàn bộ.
  • Thường giữ ngưỡng 90 tới 95 phần trăm.
  • Hoa iris giữ PC1 PC2 là gần như toàn bộ 4 đặc trưng.
# Chọn số chiều theo tỉ lệ
eig = [2.9, 0.9, 0.15, 0.05]  # giá trị riêng đã xếp giảm dần
tong = sum(eig)  # tổng phương sai
print((eig[0]+eig[1])/tong)  # tỉ lệ giữ 2 trục đầu

Pipeline và hạn chế

  • Pipeline: chuẩn hóa, tính hiệp phương sai, trích vector riêng, chọn trục, chiếu xuống.
  • Chuẩn hóa bắt buộc vì đặc trưng nghìn sẽ nuốt đặc trưng đơn vị.
  • PCA chỉ xoay tuyến tính nên bó tay với vòng tròn lồng nhau.
  • Nhạy ngoại lệ và trục mới khó diễn giải nghiệp vụ.

Ví dụ

  • Input: dữ liệu nằm trên 1 đường thẳng. Output: PC1 giữ gần 100%, PC2 gần 0.
  • Giải thích: mọi biến thiên nằm hết trên 1 hướng.
  • Input: chiếu rồi dựng ngược với đủ mọi trục. Output: khôi phục đúng dữ liệu gốc.
  • Giải thích: đủ trục thì phép xoay không mất thông tin.

💻 Bài tập

Ngôn ngữ: Python 3 với NumPy. Không dùng sklearn.decomposition.PCA trừ khi đối chiếu. Nộp vào day-084/.

Bài 1: PCA bằng ma trận hiệp phương sai

class PCA:
    def __init__(self, n_components: int | float): ...   # float trong (0,1] là tỉ lệ phương sai cần giữ
    def fit(self, X): ...
    def transform(self, X): ...
    def inverse_transform(self, Z): ...
    components_: np.ndarray            # k x d, mỗi hàng là 1 trục, độ dài 1
    explained_variance_ratio_: np.ndarray

Ràng buộc: trừ trung bình trước khi tính hiệp phương sai. Dùng np.linalg.eigh và sắp giá trị riêng giảm dần. Cố định dấu mỗi trục (phần tử có trị tuyệt đối lớn nhất mang dấu dương) để kết quả tất định.

Iris, n_components=2 -> explained_variance_ratio_ ~ [0.92, 0.05]
n_components=0.95    -> giữ 2 trục
Các trục vuông góc: components_ @ components_.T ~ I

Bài 2: PCA bằng SVD và trực quan

  1. Viết bản fit_svd dùng np.linalg.svd. So với bản eigh.
  2. Vẽ Iris trên PC1-PC2, tô màu theo loài.
  3. Vẽ scree plot: tỉ lệ phương sai từng trục và tỉ lệ cộng dồn.
  4. In "loading" của PC1: đặc trưng nào đóng góp nhiều nhất.

Bài 3: Nén ảnh và tiền xử lý (nâng cao)

  1. Bộ chữ số viết tay load_digits (8x8). Giữ k = 5, 10, 20, 40 trục. Dựng lại ảnh bằng inverse_transform. Vẽ ảnh gốc và ảnh dựng lại, in sai số.
  2. Chạy K-means (ngày 47) trên dữ liệu gốc 64 chiều và trên 10 trục PCA. So silhouette và thời gian.
  3. Chỉ ra 1 trường hợp PCA làm mất thông tin phân lớp: dữ liệu 2 lớp tách nhau theo hướng phương sai nhỏ.

✅ Tiêu chí hoàn thành

  • Kết quả khớp sklearn.decomposition.PCA (sai số 1e-8, sau khi cố định dấu).
  • Bản eigh và SVD cho cùng kết quả.
  • Có scree plot, hình Iris 2D, hình dựng lại chữ số.
  • Có ví dụ PCA làm hỏng phân lớp kèm giải thích.

❓ Câu hỏi ôn tập

  • PC1 và PC2 là gì?
  • Tỉ lệ giữ lại tính thế nào?
  • Vì sao phải chuẩn hóa trước PCA?
  • Khi nào PCA thất bại?

🌕 Bạn đã hoàn thành ngày 84. Làm hết bài tập phía trên rồi sang ngày tiếp theo.

Bớt paste mù, hiểu sâu từng dòng mình viết.

180 Days Challenge. 180 ngày cai nghiện vibe code.