0Pricing
Pandas & NumPy Academy · Lekcja

Wartości własne i przegląd SVD

Oblicz wartości i wektory własne za pomocą np.linalg.eig oraz poznaj rolę SVD w redukcji wymiarowości PCA.

Wartości własne i przegląd SVD to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Pandas & NumPy Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.

Czym są wartości własne i wektory własne

Wektor własny macierzy kwadratowej A to niezerowy wektor v spełniający warunek A @ v = lambda * v — mnożenie przez A jedynie skaluje v, nie zmieniając jego kierunku. Skalar lambda nazywa się wartością własną odpowiadającą v. Wartości własne ujawniają wewnętrzne „współczynniki rozciągania” transformacji liniowej: wartość własna równa 2 oznacza, że macierz podwaja długości w kierunku wektora własnego, natomiast ujemna wartość własna odwraca kierunek.

import numpy as np

A = np.array([[3.0, 1.0],
              [0.0, 2.0]])

eigenvalues, eigenvectors = np.linalg.eig(A)
print('Eigenvalues:', eigenvalues)
print('Eigenvectors (columns):')
print(eigenvectors)

Obliczanie wartości własnych za pomocą np.linalg.eig()

np.linalg.eig(A) zwraca krotkę (eigenvalues, eigenvectors). Wartości własne są tablicą 1-wymiarową, a wektory własne — tablicą 2-wymiarową, w której każda kolumna jest wektorem własnym. Dla rzeczywistych macierzy symetrycznych, takich jak macierze kowariancji, wartości własne są zawsze rzeczywiste, a wektory własne są ortogonalne — dla macierzy symetrycznych należy używać np.linalg.eigh(A), ponieważ działa szybciej i gwarantuje zwrócenie wyników rzeczywistych.

import numpy as np

# Symmetric matrix -> use eigh for efficiency and real eigenvalues
A = np.array([[4.0, 2.0],
              [2.0, 3.0]])

vals, vecs = np.linalg.eigh(A)
print('Eigenvalues (real):', vals)
print('Eigenvectors (orthonormal columns):')
print(vecs)

# Verify: A @ v = lambda * v for each eigenvector
for i in range(len(vals)):
    lhs = A @ vecs[:, i]
    rhs = vals[i] * vecs[:, i]
    print(f'v{i} check:', np.allclose(lhs, rhs))

Wartości własne a właściwości macierzy

Wartości własne kodują ważne właściwości macierzy. Wyznacznik jest równy iloczynowi wszystkich wartości własnych: det(A) = product(eigenvalues). Ślad (suma elementów na przekątnej) jest równy sumie wartości własnych: trace(A) = sum(eigenvalues). Macierz jest dodatnio określona (wszystkie wartości własne > 0) wtedy i tylko wtedy, gdy wszystkie jej wartości własne są dodatnie — jest to kluczowa właściwość poprawnych macierzy kowariancji i problemów optymalizacji wypukłej.

import numpy as np

A = np.array([[4.0, 2.0],
              [2.0, 3.0]])

vals, _ = np.linalg.eigh(A)
print('Eigenvalues:', vals)
print('Product (should = det):', np.prod(vals))
print('np.linalg.det:', np.linalg.det(A))
print('Sum (should = trace):', np.sum(vals))
print('np.trace:', np.trace(A))
print('Positive definite:', np.all(vals > 0))

Przegląd rozkładu według wartości osobliwych (SVD)

Rozkład według wartości osobliwych (SVD) rozkłada dowolną macierz A, nie tylko kwadratową, w postaci A = U @ S @ V.T, gdzie U i V są macierzami ortogonalnymi, a S jest macierzą diagonalną, której elementy na przekątnej to nieujemne wartości osobliwe. SVD jest najbardziej ogólnym i stabilnym numerycznie rozkładem macierzy. Stanowi podstawę PCA, kompresji obrazów, systemów rekomendacyjnych i obliczania pseudoodwrotności. np.linalg.svd(A) zwraca U, s (1-wymiarową tablicę wartości osobliwych) oraz Vh (macierz V po transpozycji).

import numpy as np

A = np.array([[1.0, 2.0, 3.0],
              [4.0, 5.0, 6.0]])

U, s, Vh = np.linalg.svd(A, full_matrices=False)
print('U shape:', U.shape)
print('s (singular values):', s)
print('Vh shape:', Vh.shape)

# Reconstruct A
A_reconstructed = U @ np.diag(s) @ Vh
print('Reconstruction correct:', np.allclose(A, A_reconstructed))

Wartości osobliwe a rząd macierzy

Wartości osobliwe (elementy na przekątnej S) są zawsze nieujemne i standardowo zapisuje się je w kolejności malejącej. Liczba niezerowych wartości osobliwych jest równa rzędowi macierzy. Wartości osobliwe bliskie zeru wskazują na prawie liniową zależność między wierszami lub kolumnami. Największa wartość osobliwa wyznacza normę spektralną macierzy, a stosunek największej do najmniejszej niezerowej wartości osobliwej jest liczbą uwarunkowania używaną do pomiaru stabilności numerycznej.

import numpy as np

# Full-rank matrix
A = np.random.rand(5, 3)
U, s, Vh = np.linalg.svd(A, full_matrices=False)
print('Singular values:', np.round(s, 4))
print('Rank (non-zero sv):', np.linalg.matrix_rank(A))
print('Condition number:', s[0] / s[-1])

# Rank-deficient matrix
B = np.array([[1.0, 2.0], [2.0, 4.0], [3.0, 6.0]])
_, sb, _ = np.linalg.svd(B, full_matrices=False)
print('Rank-deficient sv:', np.round(sb, 8))

SVD i PCA: związek między nimi

Analizę głównych składowych (PCA) można zaimplementować bezpośrednio za pomocą SVD. Po wycentrowaniu macierzy danych X (odjęciu średnich kolumn) prawe wektory osobliwe w Vh są głównymi składowymi, a kwadraty wartości osobliwych podzielone przez n-1 są wyjaśnionymi wariancjami. PCA w bibliotece Sklearn korzysta dokładnie z tego podejścia. Zrozumienie tego związku pozwala implementować PCA od podstaw lub dostosowywać je do redukcji wymiarowości.

import numpy as np

np.random.seed(0)
X = np.random.randn(100, 4)

# Center the data
X_centered = X - X.mean(axis=0)

# SVD-based PCA
U, s, Vh = np.linalg.svd(X_centered, full_matrices=False)

# Variance explained by each component
var_explained = (s ** 2) / (X.shape[0] - 1)
total_var = var_explained.sum()
print('Variance explained ratio:', np.round(var_explained / total_var, 3))

# Project onto top 2 principal components
X_pca = X_centered @ Vh[:2].T
print('Reduced shape:', X_pca.shape)

Przybliżenie niskiego rzędu za pomocą SVD

SVD umożliwia przybliżanie macierzy niskiego rzędu: należy zachować tylko k największych wartości osobliwych i odpowiadających im wektorów, a następnie odtworzyć przybliżenie oryginalnej macierzy. Jest to podstawa kompresji obrazów i filtrowania kolaboracyjnego stosowanego w rekomendacjach. Obcięty rozkład SVD U[:, :k] @ np.diag(s[:k]) @ Vh[:k, :] daje najlepsze przybliżenie rzędu k w sensie metody najmniejszych kwadratów (twierdzenie Eckarta-Younga).

import numpy as np

np.random.seed(1)
A = np.random.rand(20, 15)

U, s, Vh = np.linalg.svd(A, full_matrices=False)

# Rank-3 approximation
k = 3
A_approx = U[:, :k] @ np.diag(s[:k]) @ Vh[:k, :]

error = np.linalg.norm(A - A_approx, 'fro')
total = np.linalg.norm(A, 'fro')
print(f'Approximation error: {error/total:.3f} (fraction of total)')
print(f'Top-3 singular values capture {(s[:3]**2).sum()/(s**2).sum():.1%} of variance')

Rozkład własny a SVD: kiedy używać którego

Rozkładu własnego (np.linalg.eig lub eigh) należy używać, gdy mają Państwo kwadratową macierz symetryczną i chcą zrozumieć jej osie główne — na przykład macierz kowariancji w PCA lub macierze przejścia łańcuchów Markowa. SVD (np.linalg.svd) należy stosować, gdy macierz jest prostokątna lub gdy potrzebna jest maksymalna stabilność numeryczna. SVD zawsze istnieje, natomiast rozkład własny może generować liczby zespolone dla macierzy niesymetrycznych.

import numpy as np

# Non-symmetric matrix: eigenvalues may be complex
A = np.array([[0.0, -1.0],
              [1.0,  0.0]])
vals, _ = np.linalg.eig(A)
print('Eigenvalues (complex for rotation):', vals)

# SVD always gives real singular values
_, s, _ = np.linalg.svd(A)
print('Singular values (always real):', s)

Twierdzenie spektralne dla macierzy symetrycznych

Twierdzenie spektralne mówi, że każdą rzeczywistą macierz symetryczną A można rozłożyć w postaci A = Q @ diag(eigenvalues) @ Q.T, gdzie Q jest ortogonalna (Q.T = Q⁻¹). Oznacza to, że macierze symetryczne zawsze można diagonalizować, uzyskując rzeczywiste wartości własne i ortogonalne wektory własne. Macierze kowariancji, macierze jąder w SVM oraz macierz Hessego w optymalizacji są symetryczne, dlatego twierdzenie to ma powszechne zastosowanie w teorii uczenia maszynowego.

import numpy as np

A = np.array([[5.0, 2.0, 1.0],
              [2.0, 3.0, 0.0],
              [1.0, 0.0, 4.0]])

vals, Q = np.linalg.eigh(A)
print('Eigenvalues:', np.round(vals, 4))

# Reconstruct A = Q @ diag(vals) @ Q.T
A_reconstructed = Q @ np.diag(vals) @ Q.T
print('Reconstruction correct:', np.allclose(A, A_reconstructed))
print('Q is orthogonal:', np.allclose(Q.T @ Q, np.eye(3)))

Praktyka: iteracja potęgowa dla dominującej wartości własnej

Jeśli potrzebują Państwo tylko największej wartości własnej i odpowiadającego jej wektora własnego, iteracja potęgowa jest znacznie wydajniejsza niż obliczanie wszystkich wartości własnych. Należy rozpocząć od losowego wektora, wielokrotnie mnożyć go przez A i normalizować, aż zbiegnie do dominującego wektora własnego. Tak działał oryginalny algorytm PageRank firmy Google. NumPy sprowadza każdą iterację do pojedynczego mnożenia macierzy przez wektor za pomocą @.

import numpy as np

A = np.array([[4.0, 1.0, 2.0],
              [1.0, 3.0, 0.0],
              [2.0, 0.0, 2.0]])

v = np.random.rand(3)
for _ in range(50):
    v = A @ v
    v = v / np.linalg.norm(v)

eigenvalue_approx = v @ A @ v
print('Dominant eigenvector:', np.round(v, 4))
print('Approx eigenvalue:', round(eigenvalue_approx, 4))

# Verify with eigh
vals, vecs = np.linalg.eigh(A)
print('True max eigenvalue:', round(vals[-1], 4))

Używanie np.linalg.svd w rzeczywistych potokach

W rzeczywistym potoku danych SVD służy do redukcji szumu i kompresji danych. Po dopasowaniu SVD do danych treningowych zachowuje się tylko k najlepszych składowych, które obejmują 95% wariancji. Zmniejsza to wymiarowość nowych danych przed przekazaniem ich do klasyfikatora lub reg resora, przyspieszając trenowanie i często poprawiając zdolność generalizacji przez usunięcie zaszumionych wymiarów. SVD należy zawsze dopasowywać wyłącznie do danych treningowych, a następnie stosować tę samą transformację do danych testowych.

import numpy as np

np.random.seed(7)
X_train = np.random.randn(200, 50)
X_test = np.random.randn(40, 50)

# Fit on training data
X_mean = X_train.mean(axis=0)
X_centered = X_train - X_mean
U, s, Vh = np.linalg.svd(X_centered, full_matrices=False)

# Choose k to capture 90% variance
cumvar = np.cumsum(s**2) / (s**2).sum()
k = np.searchsorted(cumvar, 0.9) + 1
print(f'Components to capture 90% variance: {k}')

# Transform test data using the same Vh
X_test_reduced = (X_test - X_mean) @ Vh[:k].T
print('Reduced test shape:', X_test_reduced.shape)

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat koncepcji analizy danych z tej lekcji.

Podsumowanie lekcji

W tej lekcji nauczyli się Państwo, że: np.linalg.eig()/eigh() obliczają wartości własne i wektory własne, które ujawniają wewnętrzne kierunki rozciągania macierzy, np.linalg.svd() rozkłada dowolną macierz na U, wartości osobliwe i Vh, umożliwiając PCA oraz przybliżanie macierzy niskiego rzędu, a wartości osobliwe określają wariancję uchwyconą przez każdą składową i wyznaczają rząd macierzy. W następnej części zajmiemy się obsługą dużych zbiorów danych przez strumieniowe odczytywanie plików CSV w fragmentach.

Często zadawane pytania

Czy lekcja „Wartości własne i przegląd SVD” jest bezpłatna?

Tak — pełny tekst „Wartości własne i przegląd SVD” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Pandas & NumPy Academy, przejdź na CoddyKit PRO. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wartości własne i przegląd SVD”?

Oblicz wartości i wektory własne za pomocą np.linalg.eig oraz poznaj rolę SVD w redukcji wymiarowości PCA. Ćwiczysz Pandas & NumPy Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Pandas & NumPy Academy?

Nie wymagamy żadnego doświadczenia. Pandas & NumPy Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Wartości własne i przegląd SVD”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Pandas & NumPy Academy?

Tak. Każda lekcja Pandas & NumPy Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Mnożenie macierzy za pomocą np.matmul i @
  2. Wyznaczniki, macierze odwrotne i transpozycje
  3. Rozwiązywanie układów równań liniowych
  4. Wartości własne i przegląd SVD
← Powrót do Pandas & NumPy Academy