如何反轉 PCA 並從幾個主成分重建原始變量?
主成分分析(PCA)可用於降維。在執行了這樣的降維之後,如何從少量的主成分中近似地重構原始變量/特徵?
或者,如何從數據中刪除或丟棄幾個主要成分?
換句話說,如何逆轉 PCA?
鑑於 PCA 與奇異值分解 (SVD) 密切相關,同樣的問題可以提出如下:如何反轉 SVD?
PCA 計算協方差矩陣(“主軸”)的特徵向量,並按其特徵值(解釋方差的數量)對它們進行排序。然後可以將居中的數據投影到這些主軸上以產生主成分(“分數”)。出於降維的目的,可以只保留主成分的一個子集並丟棄其餘部分。(請參閱此處了解外行對 PCA 的介紹。)
讓成為數據矩陣行(數據點)和列(變量或特徵)。減去平均向量後從每一行,我們得到居中的數據矩陣. 讓成為一些矩陣我們要使用的特徵向量;這些通常是具有最大特徵值的特徵向量。然後PCA 投影矩陣(“分數”)將簡單地由下式給出.
如下圖所示:第一個子圖顯示了一些居中的數據(與我在鏈接線程中的動畫中使用的數據相同)及其在第一個主軸上的投影。第二個子圖僅顯示此投影的值;維度已從 2 減少到 1:
為了能夠從這一主成分重建原始的兩個變量,我們可以將其映射回尺寸與. 實際上,每個 PC 的值都應該放在與投影相同的向量上;比較子圖 1 和 3。結果由下式給出. 我在上面的第三個子圖中顯示它。得到最終的重建,我們需要添加均值向量對此:
請注意,可以通過乘以直接從第一個子圖到第三個子圖與矩陣; 它被稱為投影矩陣。我摔倒使用特徵向量,然後是單位矩陣(不執行降維,因此“重構”是完美的)。如果僅使用特徵向量的子集,則它不是身份。
這適用於任意點在 PC 空間中;它可以通過映射到原始空間.
丟棄(移除)領先的 PC
有時人們想丟棄(移除)一個或幾個領先的 PC 並保留其餘部分,而不是保留領先的 PC 並丟棄其餘部分(如上所述)。在這種情況下,所有公式都保持完全相同,但是應該由所有主軸組成,除了要丟棄的那些。換句話說,應始終包括想要保留的所有 PC。
關於 PCA 相關性的警告
當對相關矩陣(而不是協方差矩陣)進行 PCA 時,原始數據不僅通過減法居中 但也可以通過將每列除以其標準偏差來縮放. 在這種情況下,要重建原始數據,需要對和然後才加回平均向量.
圖像處理示例
這個話題經常出現在圖像處理的背景下。考慮Lenna - 圖像處理文獻中的標準圖像之一(按照鏈接查找它的來源)。在左下方,我顯示了這個的灰度變體圖片(此處提供文件)。
我們可以將此灰度圖像視為數據矩陣. 我對其執行 PCA 併計算使用前 50 個主成分。結果顯示在右側。
恢復 SVD
PCA 與奇異值分解 (SVD) 密切相關,請參閱 SVD 和 PCA 之間的關係。如何使用 SVD 執行 PCA?更多細節。如果一個矩陣被 SVD 編輯為並且選擇一個維向量表示“減少”中的點-空間尺寸,然後將其映射回尺寸需要乘以.
R、Matlab、Python 和 Stata 中的示例
我將對Fisher Iris 數據進行 PCA ,然後使用前兩個主成分對其進行重建。我在協方差矩陣上做 PCA,而不是在相關矩陣上,即我沒有在這裡縮放變量。但我仍然必須添加平均值。一些包,比如 Stata,通過標準語法來處理這個問題。感謝@StasK 和@Kodiologist 對代碼的幫助。
我們將檢查第一個數據點的重建,即:
5.1 3.5 1.4 0.2
MATLAB
load fisheriris X = meas; mu = mean(X); [eigenvectors, scores] = pca(X); nComp = 2; Xhat = scores(:,1:nComp) * eigenvectors(:,1:nComp)'; Xhat = bsxfun(@plus, Xhat, mu); Xhat(1,:)
輸出:
5.083 3.5174 1.4032 0.21353
R
X = iris[,1:4] mu = colMeans(X) Xpca = prcomp(X) nComp = 2 Xhat = Xpca$x[,1:nComp] %*% t(Xpca$rotation[,1:nComp]) Xhat = scale(Xhat, center = -mu, scale = FALSE) Xhat[1,]
輸出:
Sepal.Length Sepal.Width Petal.Length Petal.Width 5.0830390 3.5174139 1.4032137 0.2135317
有關圖像 PCA 重建的 R 示例,另請參見此答案。
Python
import numpy as np import sklearn.datasets, sklearn.decomposition X = sklearn.datasets.load_iris().data mu = np.mean(X, axis=0) pca = sklearn.decomposition.PCA() pca.fit(X) nComp = 2 Xhat = np.dot(pca.transform(X)[:,:nComp], pca.components_[:nComp,:]) Xhat += mu print(Xhat[0,])
輸出:
[ 5.08718247 3.51315614 1.4020428 0.21105556]
請注意,這與其他語言的結果略有不同。那是因為 Python 版本的 Iris 數據集包含錯誤。
斯塔塔
webuse iris, clear pca sep* pet*, components(2) covariance predict _seplen _sepwid _petlen _petwid, fit list in 1 iris seplen sepwid petlen petwid _seplen _sepwid _petlen _petwid setosa 5.1 3.5 1.4 0.2 5.083039 3.517414 1.403214 .2135317