Собственные значения и обзор SVD
Вычислите собственные значения и собственные векторы с помощью np.linalg.eig и поймите, как SVD лежит в основе снижения размерности методом PCA
«Собственные значения и обзор SVD» — бесплатный урок Pandas & NumPy Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Pandas & NumPy Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Что такое собственные значения и собственные векторы?
Собственный вектор квадратной матрицы A — это ненулевой вектор v, такой что A @ v = lambda * v: умножение на A лишь изменяет масштаб v, но не меняет его направление. Скаляр lambda называется собственным значением, соответствующим v. Собственные значения показывают внутренние «коэффициенты растяжения» линейного преобразования: собственное значение 2 означает, что матрица удваивает длины в направлении собственного вектора; отрицательное собственное значение меняет направление на противоположное.
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)Вычисление собственных значений с помощью np.linalg.eig()
np.linalg.eig(A) возвращает кортеж (eigenvalues, eigenvectors). Собственные значения представлены одномерным массивом, а собственные векторы — двумерным массивом, где каждый столбец является собственным вектором. Для вещественных симметричных матриц (например, ковариационных матриц) собственные значения всегда вещественны, а собственные векторы ортогональны — для симметричных матриц используйте np.linalg.eigh(A), поскольку эта функция работает быстрее и гарантированно возвращает вещественные результаты.
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))Собственные значения и свойства матриц
Собственные значения содержат важные сведения о свойствах матрицы. Определитель равен произведению всех собственных значений: det(A) = product(eigenvalues). След (сумма диагональных элементов) равен сумме собственных значений: trace(A) = sum(eigenvalues). Матрица является положительно определённой (все собственные значения > 0) только тогда, когда все её собственные значения положительны — это важное свойство корректных ковариационных матриц и задач выпуклой оптимизации.
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))Обзор сингулярного разложения (SVD)
Сингулярное разложение (SVD) раскладывает любую матрицу A, а не только квадратную, в виде A = U @ S @ V.T, где U и V — ортогональные матрицы, а S — диагональная матрица с неотрицательными сингулярными значениями на диагонали. SVD — наиболее общее и численно устойчивое разложение матрицы. Оно лежит в основе PCA, сжатия изображений, рекомендательных систем и вычисления псевдообратной матрицы. np.linalg.svd(A) возвращает U, s (одномерный массив сингулярных значений) и Vh (транспонированную V).
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))Сингулярные значения и ранг матрицы
Сингулярные значения (элементы диагонали S) всегда неотрицательны и обычно перечисляются в порядке убывания. Число ненулевых сингулярных значений равно рангу матрицы. Сингулярные значения, близкие к нулю, указывают на почти линейную зависимость строк или столбцов. Наибольшее сингулярное значение задаёт спектральную норму матрицы, а отношение наибольшего сингулярного значения к наименьшему ненулевому является числом обусловленности, используемым для оценки численной устойчивости.
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 и PCA: связь между ними
Метод главных компонент (PCA) можно реализовать непосредственно с помощью SVD. После центрирования матрицы данных X (вычитания средних значений столбцов) правые сингулярные векторы в Vh являются главными компонентами, а квадраты сингулярных значений, разделённые на n-1, — объяснёнными дисперсиями. PCA в sklearn использует именно этот подход. Понимание этой связи позволяет реализовать или настроить PCA с нуля для снижения размерности.
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)Низкоранговая аппроксимация с помощью SVD
SVD позволяет выполнять низкоранговую аппроксимацию матрицы: сохранять только k наибольших сингулярных значений и векторов, а затем восстанавливать приближение исходной матрицы. Это лежит в основе сжатия изображений и коллаборативной фильтрации для построения рекомендаций. Усечённое SVD U[:, :k] @ np.diag(s[:k]) @ Vh[:k, :] даёт наилучшее приближение ранга k в смысле метода наименьших квадратов (теорема Эккарта — Янга).
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')Собственное разложение и SVD: что выбрать
Используйте собственное разложение (np.linalg.eig или eigh), если у Вас есть квадратная симметричная матрица и Вы хотите понять её главные оси — например, ковариационную матрицу в PCA или матрицы переходов Маркова. Используйте SVD (np.linalg.svd), если Ваша матрица прямоугольная или Вам требуется максимальная численная устойчивость. SVD существует всегда, тогда как собственное разложение для несимметричных матриц может давать комплексные числа.
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)Спектральная теорема для симметричных матриц
Спектральная теорема утверждает, что любую вещественную симметричную матрицу A можно разложить в виде A = Q @ diag(eigenvalues) @ Q.T, где Q — ортогональная матрица (Q.T = Q⁻¹). Это означает, что симметричные матрицы всегда диагонализируемы, имеют вещественные собственные значения и ортогональные собственные векторы. Ковариационные матрицы, матрицы ядер в SVM и матрица Гессе в задачах оптимизации симметричны, поэтому эта теорема имеет универсальное значение в теории машинного обучения.
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)))Практика: степенная итерация для доминирующего собственного значения
Если Вам требуется только наибольшее собственное значение и соответствующий ему собственный вектор, степенная итерация намного эффективнее вычисления всех собственных значений. Начните со случайного вектора, многократно умножайте его на A и нормируйте — итерации сойдутся к доминирующему собственному вектору. Именно так работал исходный алгоритм PageRank от Google. NumPy позволяет выполнять каждую итерацию одним умножением матрицы на вектор с помощью @.
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))Использование np.linalg.svd в реальных конвейерах
В реальном конвейере обработки данных SVD используют для снижения шума и сжатия данных. После обучения SVD на обучающих данных сохраняют только первые k компонент, которые охватывают 95% дисперсии. Это уменьшает размерность новых данных перед их передачей классификатору или регрессору, ускоряет обучение и часто улучшает обобщающую способность модели за счёт удаления зашумлённых измерений. Всегда обучайте SVD только на обучающих данных и применяйте одно и то же преобразование к тестовым данным.
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)Быстрая проверка
Проверьте, насколько хорошо Вы понимаете понятия анализа данных из этого урока.
Итоги урока
В этом уроке Вы узнали, что np.linalg.eig()/eigh() вычисляют собственные значения и собственные векторы, раскрывающие внутренние направления растяжения матрицы; np.linalg.svd() раскладывает любую матрицу на U, сингулярные значения и Vh, что позволяет выполнять PCA и низкоранговую аппроксимацию; а сингулярные значения количественно характеризуют дисперсию, объясняемую каждой компонентой, и определяют ранг матрицы. Далее мы рассмотрим обработку больших наборов данных потоково, считывая файлы CSV частями.
Часто задаваемые вопросы
Урок «Собственные значения и обзор SVD» бесплатный?
Да — полный текст урока «Собственные значения и обзор SVD» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Pandas & NumPy Academy, подпишись на CoddyKit PRO. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Чему я научусь в уроке «Собственные значения и обзор SVD»?
Вычислите собственные значения и собственные векторы с помощью np.linalg.eig и поймите, как SVD лежит в основе снижения размерности методом PCA Ты практикуешь Pandas & NumPy Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Pandas & NumPy Academy?
Предыдущий опыт не требуется. Pandas & NumPy Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Собственные значения и обзор SVD»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Pandas & NumPy Academy?
Да. Каждый урок Pandas & NumPy Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Умножение матриц с помощью np.matmul и @
- Определители, обратные матрицы и транспонирование
- Решение систем линейных уравнений
- Собственные значения и обзор SVD