知識點回顧:
- 線性代數概念回顧(可不掌握)
- 奇異值推導(可不掌握)
- 奇異值的應用
- 特征降維:對高維數據減小計算量、可視化
- 數據重構:比如重構信號、重構圖像(可以實現有損壓縮,k 越小壓縮率越高,但圖像質量損失越大)
- 降噪:通常噪聲對應較小的奇異值。通過丟棄這些小奇異值并重構矩陣,可以達到一定程度的降噪效果。
- 推薦系統:在協同過濾算法中,用戶-物品評分矩陣通常是稀疏且高維的。SVD (或其變種如 FunkSVD, SVD++) 可以用來分解這個矩陣,發現潛在因子 (latent factors),從而預測未評分的項。這里其實屬于特征降維的部分。
- 奇異矩陣SVD分解
對于任何矩陣(如結構化數據可以變為:樣本*特征的矩陣,圖像數據天然就是矩陣),均可做等價的奇異值SVD分解,對于分解后的矩陣,可以選取保留前K個奇異值及其對應的奇異向量,重構原始矩陣,可以通過計算Frobenius 范數相對誤差來衡量原始矩陣和重構矩陣的差異。
ps:在進行 SVD 之前,通常需要對數據進行標準化(均值為 0,方差為 1),以避免某些特征的量綱差異對降維結果的影響。
作業:嘗試利用svd來處理心臟病預測,看下精度變化
(一)SVD介紹
#SVD 的奇異值是通過對 A^T A?或 A A^T的特征值取平方根得到的,特征向量則與奇異向量相關
#在 SVD 中,我們構造 A^T A?和 A A^T,這兩個矩陣都是對稱矩陣,因此可以進行特征值分解,進而求解奇異值和奇異向量
#SVD 是一種更廣義的矩陣分解方法,適用于非方陣,而特征值分解是 SVD 計算的基礎步驟。
- 總結:
- 正交矩陣:列向量正交且單位化,在 SVD 中用于旋轉或反射(U?和 V)。
- 特征值與特征向量:描述矩陣在某些方向上的縮放特性,是計算奇異值的基礎。
- 對稱矩陣:具有實特征值和正交特征向量,SVD 通過構造 A^T A?和 A A^T?利用其性質。
- 矩陣分解:將復雜矩陣分解為簡單矩陣乘積,是降維和數據分析的核心工具。
SVD通過將矩陣分解為奇異值和正交基,揭示了數據的本質結構。其輸入為任意矩陣,輸出為三個具有明確意義的子矩陣,廣泛應用于降維、推薦、NLP等領域
(二)SVD的輸入和輸出
- 輸入:一個任意的矩陣?AA,尺寸為?m×n(其中?m?是行數,n是列數,可以是矩形矩陣,不必是方陣)。
奇異值分解(SVD)得到的三個矩陣?U、Σ?和?VT?各有其特定的意義和用途:
-
U(左奇異向量矩陣):
- 是一個?m×m?的正交矩陣,列向量是矩陣?AAT?的特征向量。
- 作用:表示原始矩陣?A在行空間(樣本空間)中的主方向或基向量。簡單來說,U?的列向量描述了數據在行維度上的“模式”或“結構”。
- 應用:在降維中,U的前幾列可以用來投影數據到低維空間,保留主要信息(如在圖像處理中提取主要特征)。
-
Σ(奇異值矩陣):
- 是一個?m×n的對角矩陣,對角線上的值是奇異值(singular values),按降序排列,非負。
- 作用:奇異值表示原始矩陣?A?在每個主方向上的“重要性”或“能量”。較大的奇異值對應更重要的特征,較小的奇異值對應噪聲或次要信息。
- 應用:通過選擇前?k?個較大的奇異值,可以實現降維,丟棄不重要的信息(如數據壓縮、去噪)。
-
VT(右奇異向量矩陣的轉置):
- 是?V?的轉置,V?是一個?n×n的正交矩陣,列向量是矩陣?ATA?的特征向量。
- 作用:表示原始矩陣?A在列空間(特征空間)中的主方向或基向量。簡單來說,V?的列向量描述了數據在列維度上的“模式”或“結構”。
- 應用:類似?U,V的前幾列可以用來投影數據到低維空間,提取主要特征。
整體作用:
結合起來,A=UΣVT 意味著原始矩陣?A可以被分解為一系列主方向(U和 V)和對應的權重(Σ)的組合。這種分解揭示了數據的內在結構。
主要應用:
- 降維:通過保留前?k?個奇異值及其對應的?U?和?V?的列向量,可以近似重建A,減少數據維度(如 PCA 的基礎)。
- 數據壓縮:如圖像壓縮,丟棄小的奇異值以減少存儲空間。
- 去噪:小的奇異值往往對應噪聲,丟棄它們可以提高數據質量。
- 推薦系統:如矩陣分解,用于預測用戶評分矩陣中的缺失值。
簡單來說,U、Σ?和?VT?提供了數據的核心結構信息,幫助我們在保留主要信息的同時簡化數據處理
- 輸出:
SVD 將矩陣?A?分解為三個矩陣的乘積形式,即?A=UΣVT
?(三)奇異值應用——降維/數據壓縮
奇異值排序——篩選——降維和近似——對應向量
篩選靠前的k個對角線上值(奇異值),取U陣前k列和Σ前k奇異值和VT前k行可實現降維
總結:SVD 分解后原始矩陣是等價的,但通過篩選排序靠前的奇異值和對應的向量,我們可以實現降維,保留數據的主要信息,同時減少計算量和噪聲影響。這種方法是許多降維算法(如 PCA)和數據處理技術的基礎。
- 問題:在機器學習中,如果對訓練集進行 SVD 降維后訓練模型,而測試集的特征數量與降維后的訓練集不一致(測試集仍保持原始特征數量),該如何處理?
答:同樣地對測試集進行等效降維(進行相同變換) ,若對測試集單獨進行 SVD,會得到不同的 V^T?矩陣,導致測試集和訓練集的低維空間不一致,模型無法正確處理測試數據
(四)作業
import warnings
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
warnings.filterwarnings("ignore")# 設置中文字體(解決中文顯示問題)
plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系統常用黑體字體
plt.rcParams['axes.unicode_minus'] = False # 正常顯示負號
data = pd.read_csv('heart.csv')
# 最開始也說了 很多調參函數自帶交叉驗證,甚至是必選的參數,你如果想要不交叉反而實現起來會麻煩很多
# 所以這里我們還是只劃分一次數據集
from sklearn.model_selection import train_test_split
X = data.drop(['target'], axis=1) # 特征,axis=1表示按列刪除
y = data['target'] # 標簽
# # 按照8:2劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 80%訓練集,20%測試集
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
np.random.seed(42)
print(f"訓練集形狀: {X_train.shape}")
print(f"測試集形狀: {X_test.shape}")
U_train, sigma_train, Vt_train = np.linalg.svd(X_train, full_matrices=False) ##full_matrices=False 表示只計算 U 和 Vt 的前 k 列,其中 k 是矩陣 A 的秩。進行經濟SVD分解
print(f"Vt_train 矩陣形狀: {Vt_train.shape}")
# 選擇保留的奇異值數量 k
k = 8
Vt_k = Vt_train[:k, :] # 保留前 k 行,形狀為 (k, 50)
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}")
# 計算訓練集的近似誤差(可選,僅用于評估降維效果)
#近似重構矩陣 A,常用于信號or圖像篩除噪聲
X_train_approx = U_train[:, :k] @ np.diag(sigma_train[:k]) @ Vt_k # 取 U 的前 k 列,因為要保持行數不變;# 取前 k 個奇異值#取Vt_k所有行#np.diag(sigma_k) :將降維后的奇異值數組 sigma_k 轉換為對角矩陣,對角線上的元素為 sigma_k 中的值,其他位置為 0。
error = np.linalg.norm(X_train - X_train_approx, 'fro') / np.linalg.norm(X_train, 'fro')
print(f"訓練集近似誤差 (Frobenius 范數相對誤差): {error}")
結果如下:
訓練集形狀: (242, 13)
測試集形狀: (61, 13)
Vt_train 矩陣形狀: (13, 13)
保留 k=8 后的 Vt_k 矩陣形狀: (8, 13)
降維后訓練集形狀: (242, 8)
降維后測試集形狀: (61, 8)
測試集準確率: 0.8688524590163934
訓練集近似誤差 (Frobenius 范數相對誤差): 0.002934026637631935
- 評價報告
from sklearn.ensemble import RandomForestClassifier #隨機森林分類器from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score # 用于評估分類器性能的指標
from sklearn.metrics import classification_report, confusion_matrix #用于生成分類報告和混淆矩陣rf_model_var = RandomForestClassifier(random_state=42) #實例化
rf_model_var.fit(X_train_reduced, y_train) # 訓練
rf_pred_var = rf_model_var.predict(X_test_reduced) #預測# 打印模型在測試集上的分類報告,展示模型的性能
# 分類報告包括精確率、召回率、F1分數等指標,幫助評估模型好壞
print("\nSVD降維后隨機森林在測試集上的分類報告:")
print(classification_report(y_test, rf_pred_var))# 打印混淆矩陣,展示模型預測的詳細結果
# 混淆矩陣顯示了真實標簽和預測標簽的對應情況,比如多少樣本被正確分類,多少被錯分
print("SVD降維后隨機森林在測試集上的混淆矩陣:")
print(confusion_matrix(y_test, rf_pred_var))
結果:
SVD降維后隨機森林在測試集上的分類報告:precision recall f1-score support0 0.81 0.90 0.85 291 0.90 0.81 0.85 32accuracy 0.85 61macro avg 0.85 0.85 0.85 61
weighted avg 0.86 0.85 0.85 61SVD降維后隨機森林在測試集上的混淆矩陣:
[[26 3][ 6 26]]
@浙大疏錦行