Pca
當 n,p 都很大時,PCA 太慢:替代方案?
問題設置
我有高維(4096)的數據點(圖像),我試圖在 2D 中可視化。為此,我以類似於 Karpathy 的以下示例代碼的方式使用 t-sne。
scikit-learn 文檔建議先使用 PCA 來降低數據的維度:
如果特徵數量非常多,強烈建議使用另一種降維方法(例如,用於密集數據的 PCA 或用於稀疏數據的 TruncatedSVD)以將維數減少到合理的數量(例如 50)。
我正在使用 Darks.Liu 的這段代碼在 Java 中執行 PCA:
//C=X*X^t / m DoubleMatrix covMatrix = source.mmul(source.transpose()).div(source.columns); ComplexDoubleMatrix eigVal = Eigen.eigenvalues(covMatrix); ComplexDoubleMatrix[] eigVectorsVal = Eigen.eigenvectors(covMatrix); ComplexDoubleMatrix eigVectors = eigVectorsVal[0]; //Sort sigen vector from big to small by eigen values List<PCABean> beans = new ArrayList<PCA.PCABean>(); for (int i = 0; i < eigVectors.columns; i++) { beans.add(new PCABean(eigVal.get(i).real(), eigVectors.getColumn(i))); } Collections.sort(beans); DoubleMatrix newVec = new DoubleMatrix(dimension, beans.get(0).vector.rows); for (int i = 0; i < dimension; i++) { ComplexDoubleMatrix dm = beans.get(i).vector; DoubleMatrix real = dm.getReal(); newVec.putRow(i, real); } return newVec.mmul(source);
它使用jblas進行線性代數運算,據我所知,這應該是最快的選擇。然而,計算特徵向量和特徵值(第 3,4 行)被證明是一個巨大的瓶頸(大約 10 分鐘,這比我在這個階段所能承受的要長得多)。
我讀過關於內核 PCA 的文章,它應該適用於維度非常大的情況,但它的運行時間是這可能是有問題的,因為我還想處理維度和示例數量都很大的情況。
正如我所看到的,我的選擇要么是“優化”PCA,要么是選擇另一種本質上更快的降維方法。
我的問題
- 是否有希望以“離線”方式使用 PCA?即,使用大量圖像數據集,對它們執行 PCA,然後使用為它們計算的主成分來減少其他(新!)數據點的維度?
- 假設我提前知道我只對前 100 個主成分感興趣,我可以加快特徵向量計算嗎?
- 是否有適合我的情況的替代降維方法(即在應用 t-sne 之前)比 PCA 更快?我正在尋找可以在 Java 中輕鬆實現的東西。
問題 1:假設您觀察到了一個數據矩陣. 由此您可以計算特徵分解. 現在的問題是:如果我們從同一人群中獲得新數據,也許會收集到一個矩陣中, 將要接近理想的正交旋轉? 戴維斯-卡漢定理和一般的矩陣微擾理論解決了這類問題(如果你能拿到副本,斯圖爾特和孫 1990 年的教科書是標準參考)。
問題2:如果你知道你只需要頂部,你肯定可以加快速度特徵向量。在 RI
rARPACK
中用於此;我確信有一個 Java 等價物,因為無論如何它們都是 fortran 包裝器。問題 3:我對 Java 實現一無所知,但是這個線程討論加速 PCA 和這個CV 線程一樣。有大量關於這類事情的研究,並且有大量使用低秩近似或隨機化等方法的方法。