tft每日頭條

 > 科技

 > pca算法進行降維的過程是什麼

pca算法進行降維的過程是什麼

科技 更新时间:2024-06-30 16:13:17

在科研、工程應用、生活中,我們所獲取的數據往往包含着很多冗餘信息,這些冗餘信息往往對數據分析造成幹擾,增加數據分析的複雜度。此時我們則需要對這些數據進行預處理,預處理的原則是:既能抓住其主要特征,又能剔除冗餘信息,從而減少數據量。PCA降維就是這樣的一種數據預處理算法。

本文首先講解PCA降維的計算原理,再使用C 與Opencv來實現該算法,并與Opencv現有的PCA函數接口進行降維結果的對比。看到這裡,可能有人會問,Opencv都有現成的函數可以調用了,為什麼還要自己去寫呢?我想說的是,對于學習者來說,重複造輪子并不是壞事,它可以讓我們更加深刻地理解造輪子的過程,從而才有改進和創新的機會,相反,如果隻是使用别人造好的輪子,不深刻理解其構造原理,壓根就沒有改進創新的空間了。

1. 計算原理

假設有m行n列的數據,計為矩陣X0,其每一行數據看作一個一維行向量,那麼該數據本來有m個一維行向量,我們要使用PCA降維算法把其降為k個一維行向量(k < m),計算過程如下:

(1) 求出每行數據的平均值。

(2) 去平均處理,把每行數據都減去本行數據的平均值。

(3) 去平均處理之後,同樣得到m行n列的數據,計為矩陣X1。

(4) 按以下公式計算X0的協方差矩陣,其中“*”表示矩陣乘法,得到的協方差矩陣Cov為m行m列矩陣:

pca算法進行降維的過程是什麼(PCA降維的計算原理與應用)1

(5) 計算協方差矩陣Cov的特征值與對應的特征向量。得到m個特征值,對應m個特征向量,其中每個特征向量的長度又為m,也即所有特征向量組成m行m列的矩陣。

(6) 将特征值按照從大到小排列,并根據排列後特征值的順序來按行從上到下排列特征向量(每個特征向量為一行),使特征值與特征向量仍保持對應。

比如本來特征值依次為a1,a2,a3,a4,a5,對應的特征向量為:

v1

v2

v3

v4

v5

排序之後,a3>a1>a4>a5>a2,那麼特征向量的順序也作對應的調整:

v3

v1

v4

v5

v2

此時計特征向量組成的矩陣為V。

(7) 取矩陣V的前k行數據,得到k行m列的矩陣P,計算Y=P*X1,Y矩陣即為最終得到的k行n列的降維數據,從而實現把數據從m維降為n維。

上代碼:

voiddo_PCA(Matsrc,Mat&pca,intk) { if (src.rows <= 1 || src.cols <= 1) { return; } k = k > src.rows ? src.rows : k; Mat src_float; src.convertTo(src_float,CV_32F); //求每行的平均值 Mat col_mean = Mat::zeros(1, src.rows, CV_32FC1); float *col_mean_p = col_mean.ptr<float>(0); for (int i = 0; i < src_float.rows; i ) { float *p = src_float.ptr<float>(i); for (int j = 0; j < src_float.cols; j ) { col_mean_p[i] = p[j]; } } col_mean /= src_float.cols; //去平均值 for (int i = 0; i < src_float.rows; i ) { float *p = src_float.ptr<float>(i); for (int j = 0; j < src_float.cols; j ) { p[j] = p[j] - col_mean_p[i]; } } //計算協方差矩陣 Mat X = src_float*src_float.t(); X = X / src_float.cols; Mat eValuesMat, eVectorsMat; //調用opencv接口計算特征值與特征向量 eigen(X,eValuesMat,eVectorsMat);//這裡得到的特征值已經按照從大到小排序了,特征向量也與特征值相對應 Mat Vectors_k; eVectorsMat(Rect(0,0,eVectorsMat.cols,k)).copyTo(Vectors_k);//取特征向量的前k行,k*r pca=Vectors_k*src_float;//k*r*r*c=k*c pca=pca.clone();//确保矩陣連續,拷貝一份 printf("pca.rows=%d,pca.cols=%d\n",pca.rows,pca.cols); }

測試代碼:

void pca_test(void) { Matimg=imread("lena.jpg",CV_LOAD_IMAGE_GRAYSCALE); intk=100;//從圖像原有的m行降為100行,列不變 Matpca_m; do_PCA(img,pca_m,k); imshow("原圖", img); imshow("本文實現算法 PCA降維後", pca_m); //使用Opencv的PCA函數接口 PCApca(img,Mat(),CV_PCA_DATA_AS_COL,k); Matdst=pca.project(img);//dst則為最終降維數據 imshow("Opencv PCA降維後",dst); waitKey(0); }

運行上述代碼,得到的結果如下。可以看到,本文實現的算法與Opencv函數的計算結果是一緻的,說明我們的計算過程沒錯,鼓掌~再接再厲~

pca算法進行降維的過程是什麼(PCA降維的計算原理與應用)2

原圖

pca算法進行降維的過程是什麼(PCA降維的計算原理與應用)3

本文實現的PCA算法的降維結果

pca算法進行降維的過程是什麼(PCA降維的計算原理與應用)4

Opencv現有的PCA算法的降維結果

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved