3.2 PCA — Analiza componentelor principale
Când ai 100 de coloane, PCA găsește câteva „direcții esențiale" care păstrează aproape toată informația — pentru vizualizare, viteză și reducerea zgomotului.
Teorie
Reducerea dimensionalității
Multe coloane spun povești suprapuse (înălțimea în cm și în inch, notele la materii înrudite). PCA construiește componente principale: combinații liniare noi ale coloanelor, alese astfel încât prima componentă să capteze cea mai mare parte din variația datelor, a doua — maximul rămas (perpendiculară pe prima), și așa mai departe.
Intuiție: datele sunt un nor de puncte; PCA rotește axele astfel încât prima axă să treacă prin „lungimea" norului. Dacă norul e plat, a treia dimensiune abia mai contează — o poți tăia.
Varianța explicată — câte componente păstrezi
explained_variance_ratio_ spune ce procent din informație duce fiecare componentă.
Regulă practică: păstrezi componentele care cumulează 90–95%. Alternativ, îi ceri direct lui
sklearn: PCA(n_components=0.95).
Proiecția în spații reduse
transform proiectează datele pe noile axe; inverse_transform le aduce
aproximativ înapoi — diferența este informația pierdută. Proiecția pe primele 2 componente este
cel mai comun mod de a desena date cu multe dimensiuni.
Implementarea scikit-learn
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import numpy as np
X = StandardScaler().fit_transform(df) # PCA cere date standardizate
pca = PCA()
pca.fit(X)
print(pca.explained_variance_ratio_.round(3)) # per componentă
print(np.cumsum(pca.explained_variance_ratio_).round(3)) # cumulat
# păstrăm 95% din informație
pca = PCA(n_components=0.95)
X_redus = pca.fit_transform(X)
print(X.shape, "→", X_redus.shape)
fit pentru PCA se face doar pe train —
aceeași regulă anti-leakage ca la scalare.Problemă rezolvată: cifre scrise de mână în 2D
Imaginile 8×8 cu cifre au 64 de dimensiuni. Le proiectăm cu PCA în 2D ca să vedem cum se grupează cifrele, apoi măsurăm câte componente ne trebuie pentru 95% din informație.
Soluția pas cu pas
import numpy as np, matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
X, y = load_digits(return_X_y=True) # (1797, 64)
X_s = StandardScaler().fit_transform(X)
# proiecția 2D
p2 = PCA(n_components=2).fit(X_s)
X2 = p2.transform(X_s)
plt.figure(figsize=(8, 6))
sc = plt.scatter(X2[:, 0], X2[:, 1], c=y, cmap="tab10", s=10)
plt.colorbar(sc); plt.title("Digits în primele 2 componente"); plt.show()
print("Varianță explicată de 2 componente:",
p2.explained_variance_ratio_.sum().round(3)) # ~0.22
# câte componente pentru 95%?
p95 = PCA(n_components=0.95).fit(X_s)
print("Componente pentru 95%:", p95.n_components_) # ~40 din 64
Interpretare: chiar cu doar ~22% din varianță, cifrele 0, 4 și 6 formează insule vizibile; cifrele asemănătoare grafic (3/8/9) se amestecă. Pentru separare vizuală mai bună → t-SNE/UMAP, lecția următoare.
Probleme propuse
Creează un tabel cu x1 aleator, x2 = 2·x1 + zgomot mic și
x3 independent. Rulează PCA și explică de ce prima componentă explică ~66% din
varianță.
Pentru orice dataset tabelar de pe platformă, desenează varianța explicată cumulată în funcție de numărul de componente și marchează pragurile 90% și 95%.
Compară un clasificator antrenat pe datele digits complete vs pe primele 20 de componente PCA: acuratețe și timp de antrenare. Merită reducerea?
Aplică PCA pe liniile unei imagini în tonuri de gri și reconstruiește-o cu 5, 20 și 50 de componente. Afișează cele trei versiuni una lângă alta.