奇異值SVD分解
知識點回顧:
- 線性代數概念回顧
- 奇異值推導
- 奇異值的應用
a. 特征降維:對高維數據減小計算量、可視化
b. 數據重構:比如重構信號、重構圖像(可以實現有損壓縮,k 越小壓縮率越高,但圖像質量損失越大)
c. 降噪:通常噪聲對應較小的奇異值。通過丟棄這些小奇異值并重構矩陣,可以達到一定程度的降噪效果。
d. 推薦系統:在協同過濾算法中,用戶-物品評分矩陣通常是稀疏且高維的。SVD (或其變種如 FunkSVD, SVD++) 可以用來分解這個矩陣,發現潛在因子 (latent factors),從而預測未評分的項。這里其實屬于特征降維的部分。
知識點回顧:
對于任何矩陣(如結構化數據可以變為:樣本*特征的矩陣,圖像數據天然就是矩陣),均可做等價的奇異值SVD分解,對于分解后的矩陣,可以選取保留前K個奇異值及其對應的奇異向量,重構原始矩陣,可以通過計算Frobenius 范數相對誤差來衡量原始矩陣和重構矩陣的差異。
應用:結構化數據中,將原來的m個特征降維成k個新的特征,新特征是原始特征的線性組合,捕捉了數據的主要方差信息,降維后的數據可以直接用于機器學習模型(如分類、回歸),通常能提高計算效率并減少過擬合風險。
ps:在進行 SVD 之前,通常需要對數據進行標準化(均值為 0,方差為 1),以避免某些特征的量綱差異對降維結果的影響。
作業:嘗試利用svd來處理心臟病預測,看下精度變化
筆記:
奇異值分解(Singular Value Decomposition, SVD)是線性代數中極具影響力的工具,其核心價值在于能處理任意形狀的矩陣,同時在高維數據處理場景中發揮關鍵作用。以下將從線性代數基礎回顧切入,逐步推導奇異值的數學邏輯,最終結合實際場景解析應用,形成完整的知識閉環。
一、線性代數概念回顧(SVD 的數學基礎)
SVD 的推導依賴線性代數中 “矩陣變換”“特征值與特征向量” 等核心概念,需先明確以下基礎:
1. 矩陣的幾何意義:線性變換
任意一個 m×n 矩陣 A,本質是一種從 n 維空間到 m 維空間的線性變換,其作用包括:
- 拉伸 / 壓縮:沿某個方向放大或縮小向量長度;
- 旋轉:改變向量的方向(僅當矩陣為方陣且行列式非負時可能發生);
- 投影:將高維向量映射到低維子空間(如 3 維向量投影到 2 維平面)。
例如,2×2
矩陣A = [[2,0],[0,1]]
表示:將 x 軸方向的向量拉伸 2 倍,y 軸方向的向量保持不變。
2. 特征值與特征向量(僅針對方陣)
對于 n×n
方陣A
,若存在非零向量 v
和 scalar(標量)λ
,滿足 Av = λv
,則:
v
稱為 A 的特征向量:表示矩陣 A 對該向量僅產生 “拉伸 / 壓縮”,不改變方向(或反向);λ
稱為 A 的特征值:表示拉伸 / 壓縮的比例(λ>1
拉伸,0<λ<1
壓縮,λ<0
反向拉伸)。
關鍵性質:
若方陣 A
是實對稱矩陣(滿足 A^T = A
,A^T
為 A 的轉置),則其特征向量兩兩正交,且可構成 n 維空間的標準正交基(向量長度為 1,兩兩內積為 0)。這一性質是 SVD 推導的核心前提。
3. 正交矩陣與標準正交基
若矩陣 U
滿足 U^T U = I
(I
為單位矩陣),則 U
為正交矩陣,其列向量構成標準正交基。
正交矩陣的核心作用:對向量做 “旋轉 / 反射” 變換時,不改變向量的長度和夾角(例如,將直角坐標系旋轉后,坐標軸仍垂直,向量長度不變)。
二、奇異值的推導(從數學邏輯到公式)
SVD 的目標是:將任意m×n
矩陣 A 分解為 3 個具有明確幾何意義的矩陣乘積,即 A = UΣV^T
,其中:
U
:m×m
正交矩陣(列向量為 A 的 “左奇異向量”);
Σ
:m×n
對角矩陣(對角線上的非負元素為 A 的 “奇異值”,且從大到小排列);
V^T
:n×n
正交矩陣的轉置(行向量為 A 的 “右奇異向量”)。
以下分 3 步推導,避開復雜證明,聚焦邏輯鏈:
步驟 1:構造實對稱矩陣,利用特征值性質
由于 A
是 m×n
矩陣,其轉置 A^T
是 n×m
矩陣,因此:
A^T A
是n×n
實對稱矩陣(滿足(A^T A)^T = A^T (A^T)^T = A^T A
);A A^T
是m×m
實對稱矩陣(同理滿足(A A^T)^T = A A^T
)。
根據實對稱矩陣的性質:A^T A
和 A A^T
的特征值均為非負數,且兩者有相同的非零特征值(設為 λ? ≥ λ? ≥... ≥ λ_k > 0,k ≤ min(m,n)
)。
步驟 2:定義奇異值與奇異向量
- 奇異值:將
A^T A
(或A A^T
)的非零特征值開平方,得到 A 的奇異值,即σ_i = √λ_i
(i=1,2,...,k
),且滿足σ? ≥ σ? ≥... ≥ σ_k > 0
;
對角矩陣Σ
中,前 k 個對角元素為σ?, σ?,..., σ_k
,其余元素為 0。 - 右奇異向量(V 的列向量):
取A^T A
的特征向量,按特征值從大到小排列,構成n×n
正交矩陣V
,其列向量即為A
的右奇異向量。 - 左奇異向量(U 的列向量):
對每個非零奇異值σ_i
,定義u_i = (A v_i) / σ_i
(v_i
是A^T A
的第i
個特征向量),則u_i
是A A^T
的第i
個特征向量;
將u?, u?,..., u_k
補充正交向量(若m > k
),構成m×m
正交矩陣U
,其列向量即為A
的左奇異向量。
步驟 3:驗證分解式 A = UΣV^T
將 V
的列向量 v?,..., v?
視為 n
維空間的標準正交基,對任意 n
維向量 x
,可表示為 x = c?v? +... + c?v?
(c_i
為系數)。
矩陣 A
對 x
的變換為:
A x = c?A v? +... + c?A v?
由左奇異向量定義 A v_i = σ_i u_i
(i≤k
),且 i>k
時 σ_i=0
,因此:
A x = c?σ? u? +... + c_kσ_k u_k
這意味著:A
將 n
維空間的基 v?,..., v?
,通過 “拉伸(σ_i
倍)+ 映射到 m
維空間的基 u?,..., u_k
” 實現線性變換,與 A = UΣV^T
的矩陣乘法邏輯完全一致。
三、奇異值的應用(從理論到實際場景)
SVD 的所有應用均基于一個核心規律:前 k 個最大的奇異值(σ?,..., σ_k
)包含了矩陣 A 的絕大部分信息,后面的小奇異值往往對應冗余、噪聲或次要細節。通過保留前 k 個奇異值,可在 “效果” 與 “成本”(計算量、存儲量)間找到最優平衡。
a. 特征降維:解決 “維度災難”
核心問題
高維數據(如 1000 維的用戶行為數據、10000 維的圖像像素數據)會帶來兩大挑戰:
- 計算成本高:例如計算兩個 10000 維向量的距離,需遍歷 10000 個元素;
- 可視化困難:人類僅能感知 2/3 維空間,高維數據無法直接觀察規律。
SVD 降維邏輯
對 m×n
數據矩陣 A(m 個樣本,n 個特征)做 SVD 分解 A = UΣV^T
,取前 k 個奇異值對應的:
V
的前 k 列(V_k
,n×k
矩陣);- 降維后的數據矩陣為
A_k = A V_k = U_k Σ_k
(m×k
矩陣,k 遠小于 n)。
典型場景
- 高維數據可視化:將 1000 維的商品特征數據降到 2 維,用散點圖聚類(如 “高端家電”“平價日用品” 兩類商品明顯分離);
- 加速機器學習:對文本的 TF-IDF 矩陣(
m×n
,m
為文檔數,n
為詞匯數)降維后,再輸入 SVM、KNN 等算法,計算時間可減少 90% 以上。
b. 數據重構:實現 “有損壓縮”
核心邏輯
數據重構是降維的逆過程:用降維時保留的 U_k
(m×k
)、Σ_k
(k×k
)、V_k^T
(k×n
),重構近似原矩陣 A_hat = U_k Σ_k V_k^T
。
重構的關鍵權衡:
- k越小:保留的奇異值越少 → 壓縮率越高(如圖片文件體積縮小)→ 質量損失越大(如圖片模糊);
- k越大:越接近原矩陣 → 質量越好 → 壓縮率越低。
典型場景
- 圖像壓縮:一張
1024×1024
的灰度圖(矩陣1024×1024
),取前 50 個奇異值重構,文件體積僅為原大小的(1024×50 + 50 + 1024×50)/(1024×1024) ≈ 10%
,但肉眼幾乎看不出模糊;若取前 10 個奇異值,壓縮率達 98%,但圖像細節明顯丟失; - 信號壓縮:語音信號、傳感器時序信號(如溫度監測數據),通過 SVD 丟棄小奇異值后,可在保證可辨識度的前提下,減少數據傳輸量。
c. 降噪:過濾 “無規律噪聲”
核心觀察
數據中的噪聲(如圖片的斑點、信號的雜波)通常是 “無規律的小波動”,對應的奇異值極小;而數據的核心信息(如圖片主體、信號趨勢)對應大奇異值。
降噪步驟
- 對含噪聲的矩陣
A_noise
做 SVD 分解,得到所有奇異值σ? ≥ σ? ≥... ≥ σ_k
; - 設定閾值
t
(如取t = 0.1σ?
),丟棄所有σ_i < t
的奇異值; - 用保留的大奇異值重構矩陣
A_clean = U_k Σ_k V_k^T
,即得到降噪后的數據。
典型場景
- 圖像降噪:老照片的劃痕、低光照拍攝的噪點,通過 SVD 降噪后,畫面清晰度顯著提升;
- 傳感器數據降噪:溫度傳感器采集的數據含隨機波動(噪聲),丟棄小奇異值后,可清晰看到 “白天升溫、夜間降溫” 的趨勢。
d. 推薦系統:挖掘 “潛在因子”
核心問題
用戶 - 物品評分矩陣 A
(m×n
,m 為用戶數,n 為物品數)是 “稀疏高維” 的 ——90% 以上的元素為空白(用戶未評分),無法直接用傳統方法預測空白評分。
SVD 推薦邏輯
通過 SVD(或適用于稀疏矩陣的變種,如 FunkSVD、SVD++)分解評分矩陣,發現潛在因子(Latent Factors):
U
的行向量:用戶的偏好因子(如 “喜歡科幻電影、討厭言情電影”);V
的列向量:物品的屬性因子(如 “科幻電影、言情電影”);- 空白評分預測:用戶 i 對物品 j 的評分 ≈
U_i Σ V_j^T
(即用戶偏好與物品屬性的匹配度)。
本質關聯
該應用本質是 “特征降維” 的延伸:將高維的 “用戶 - 物品” 維度,降到低維的 “潛在因子” 維度(如 50 個因子),從而解決稀疏性問題。
四、總結:SVD 的核心價值
SVD 的所有應用均圍繞 “抓住主要矛盾” 展開 —— 用少數大奇異值(核心信息)替代大量小奇異值(冗余 / 噪聲),在 “效果” 與 “成本” 間找到最優解。其之所以成為數據科學、機器學習的核心工具,正是因為它能以簡潔的數學形式,解決高維數據處理的共性問題(降維、壓縮、降噪、稀疏性),且兼具理論嚴謹性與工程實用性。
五、矩陣降維案例
import numpy as np# 創建一個矩陣 A (5x3)
A = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12],[13, 14, 15]])
print("原始矩陣 A:")
print(A)# 進行 SVD 分解
U, sigma, Vt = np.linalg.svd(A, full_matrices=False)
print("\n奇異值 sigma:")
print(sigma)# 保留前 k=1 個奇異值進行降維
k = 1
U_k = U[:, :k] # 取 U 的前 k 列,因為要保持行數不變
sigma_k = sigma[:k] # 取前 k 個奇異值
Vt_k = Vt[:k, :] # 取 Vt 的前 k 行,因為要保持列數不變# 近似重構矩陣 A,常用于信號or圖像篩除噪聲
A_approx = U_k @ np.diag(sigma_k) @ Vt_k
print("\n保留前", k, "個奇異值后的近似矩陣 A_approx:")
print(A_approx)# 計算近似誤差
error = np.linalg.norm(A - A_approx, 'fro') / np.linalg.norm(A, 'fro')
print("\n近似誤差 (Frobenius 范數相對誤差):", error)
原始矩陣 A:
[[ 1 2 3][ 4 5 6][ 7 8 9][10 11 12][13 14 15]]奇異值 sigma:
[3.51826483e+01 1.47690770e+00 9.86023090e-16]保留前 1 個奇異值后的近似矩陣 A_approx:
[[ 1.85152908 2.05208851 2.25264793][ 4.5411984 5.03310541 5.52501242][ 7.23086771 8.01412231 8.7973769 ][ 9.92053702 10.99513921 12.06974139][12.61020633 13.9761561 15.34210588]]近似誤差 (Frobenius 范數相對誤差): 0.04194136031471535
作業
import numpy as np #計算
import pandas as pd # 數據處理
from sklearn.model_selection import train_test_split #劃分訓練集&測試集
from sklearn.linear_model import LogisticRegression # 模型
from sklearn.metrics import accuracy_score # 準確度data = pd.read_csv('heart.csv')# 設置隨機種子以便結果可重復
np.random.seed(42)# 區分標簽和特征
X = data.drop('target',axis=1)
y = data['target']# 做標準化處理
from sklearn.preprocessing import StandardScalerscaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
X_scaled = scaler.transform(X)# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
print(f"訓練集形狀: {X_train.shape}")
print(f"測試集形狀: {X_test.shape}")# 對訓練集進行 SVD 分解
U_train, sigma_train, Vt_train = np.linalg.svd(X_train, full_matrices=False)
print(f"Vt_train 矩陣形狀: {Vt_train.shape}")# 選擇保留的奇異值數量 k
k = 6
Vt_k = Vt_train[:k, :] # 保留前 k 行
print(f"保留 k={k} 后的 Vt_k 矩陣形狀: {Vt_k.shape}")# 降維訓練集:X_train_reduced = X_train @ Vt_k.T
X_train_reduced = X_train @ Vt_k.T
print(f"降維后訓練集形狀: {X_train_reduced.shape}")# 使用相同的 Vt_k 對測試集進行降維:X_test_reduced = X_test @ Vt_k.T
X_test_reduced = X_test @ Vt_k.T
print(f"降維后測試集形狀: {X_test_reduced.shape}")# 訓練模型(以邏輯回歸為例)
model = LogisticRegression(random_state=42)
model.fit(X_train_reduced, y_train)# 預測并評估
y_pred = model.predict(X_test_reduced)
accuracy = accuracy_score(y_test, y_pred)
print(f"測試集準確率: {accuracy:.4f}")# 計算訓練集的近似誤差(可選,僅用于評估降維效果)
X_train_approx = U_train[:, :k] @ np.diag(sigma_train[:k]) @ Vt_k
error = np.linalg.norm(X_train - X_train_approx, 'fro') / np.linalg.norm(X_train, 'fro')
print(f"訓練集近似誤差 (Frobenius 范數相對誤差): {error:.4f}")
訓練集形狀: (242, 13)
測試集形狀: (61, 13)
Vt_train 矩陣形狀: (13, 13)
保留 k=6 后的 Vt_k 矩陣形狀: (6, 13)
降維后訓練集形狀: (242, 6)
降維后測試集形狀: (61, 6)
測試集準確率: 0.8852
訓練集近似誤差 (Frobenius 范數相對誤差): 0.5709
@浙大疏錦行