日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于PCA算法生成平均脸

發布時間:2023/12/18 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于PCA算法生成平均脸 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在智能算法專題設計課中,我們學習了PCA算法,并學會利用PCA算法生成平均臉,下面是步驟以及我的一些思考

了解PCA算法

PCA算法本質上是一種降維算法。

**PCA的算法思路:**數據從原來的坐標系轉換到新的坐標系,由數據本身決定。轉換坐標系時,以方差最大的方向作為坐標軸方向,因為數據的最大方差給出了數據的最重要的信息。第一個新坐標軸選擇的是原始數據中方差最大的方向,第二個新坐標軸選擇的是與第一個新坐標軸正交且方差次大的方向。重復該過程,重復次數為原始數據的特征維數。
**PCA算法的要點:**通過這種方式獲得的新的坐標系,我們發現,大部分方差都包含在前面幾個坐標軸中,后面的坐標軸所含的方差幾乎為0。于是,我們可以忽略余下的坐標軸,只保留前面的幾個含有絕大部分方差的坐標軸。事實上,這樣也就相當于只保留包含絕大部分方差的維度特征,而忽略包含方差幾乎為0的特征維度,也就實現了對數據特征的降維處理。

生成特征臉的步驟

輸入:訓練樣本集 D=x(1),x(2),…,x(m)D=x(1),x(2),…,x(m) ,低維空間維數 d′d′ ;
?過程:.
??第一步:對所有樣本進行中心化(去均值操作): x(i)j←x(i)j?1m∑mi=1x(i)jxj(i)←xj(i)?1m∑i=1mxj(i) ;
??第二步:計算樣本的協方差矩陣 XXTXXT ;
??第三步:?對協方差矩陣 XXTXXT 做特征值分解 ;
?第四步:取最大特征值對應的特征向量(這里可以通過能量進行選擇)
?第五步:最終得到的特征向量便是特征臉

代碼逐步分析

(1)對樣本進行中心化:

這里包括讀入所給的32張圖片,將每張圖片抽拉成一列(可以用a=a(:)的辦法),averageFace為自己寫的定義平均臉的函數。同時需要注意將原始臉數據轉換一下數據類型,否則進行中心化相減時將會因為數據類型不一致而報錯。

[averFace,oriFace]=averageFace(32,'s','.bmp'); averFace=averFace(:);%轉成一列 oriFace=double(oriFace); for i=1:32oriFace(:,i)=oriFace(:,i)-averFace; end 計算平均臉的函數: function [aver,originalFace] = averageFace(num,beforeName,endName) %計算平均臉的函數 %輸入:數據里的所有的臉,包括圖片的張數,圖片的前綴名,圖片的后綴名 %輸出:平均臉、原始的所有圖片構成的矩陣、 %首先,構造一個矩陣,用于存放每個圖片后來構成的圖像 aver=ones(10000,1); for i=1:numface=imread(strcat(beforeName,num2str(i),endName));%讀入圖片數據%每讀一張,就將它轉化為列向量column=face(:);%把轉化后的列向量添加到一個矩陣中aver=[aver column]; end %刪除矩陣的第一列:為了構造矩陣而添加的一列 aver(:,1)=[]; originalFace=aver; %計算該矩陣每一行的平均值,形成一列平均值的向量 aver=mean(aver,2); %將平均值的向量還原成矩陣,即為平均臉,返回平均臉 aver=reshape(aver,100,100); end

(2)計算樣本的協方差矩陣:

這里是(10000,32)(3210000),所以得到的協方差矩陣為10000*10000,比較大。

%第二步:計算樣本的協方差矩陣 covMatrix=oriFace*oriFace';

(3)計算樣本的特征值和特征向量:

在matlab中可以使用函數eig得到協方差矩陣的特殊值,由于協方差矩陣比較大,所以計算過程十分耗時,下面有談到另一種計算特征向量和特征值的辦法。

%第三步:對協方差矩陣作特征值分解 %獲得協方差矩陣的特征值的對角矩陣D [V,D]=eig(covMatrix); %取對角矩陣的特征值 featureValue=diag(D);

(4)根據能量找到最大的幾個特征值,并找到最大特征值對應的特征向量。

%對特征值進行從大到小的排序 bigToSmall=sort(featureValue,'descend'); %第四步:取最大的d個特征值所對應的特征向量 %這里通過能量確定d的取值 d=0;%d的初始取值為0 someEnergy=0;%前項的能量 allEnergy=sum(bigToSmall(:));%所有的特征能量 while(someEnergy/allEnergy<0.9)d=d+1;someEnergy=sum(bigToSmall(1:d,:)); end %尋找特征值對應的特征向量 featureVector=zeros(10000,1); for i=1:dnowNumber=bigToSmall(i);%從大到小找到此時的值[row,column]=find(D==nowNumber);%在原來的特征值數組中定位findVector=V(:,column);%根據原來的特征值數組位置找到其對應的特征向量featureVector=[featureVector findVector]; end featureVector=featureVector(:,2:d+1);%刪掉之前添加的數據

(5)最終找到的特征向量即為特征臉,只需要使用reshape函數轉成原始圖片大小即可。

matlab整體實現代碼

function [] = PCACalculator() %PCA算法計算出特征臉 %輸入:訓練樣本集,低維空間維度:d %輸出:特征臉 %第一步:對所有樣本進行中心化 %得到平均臉函數中,獲得的原始所有臉矩陣+平均臉矩陣 [averFace,oriFace]=averageFace(32,'s','.bmp'); averFace=averFace(:);%轉成一列 oriFace=double(oriFace); for i=1:32oriFace(:,i)=oriFace(:,i)-averFace; end %第二步:計算樣本的協方差矩陣 covMatrix=oriFace*oriFace'; %第三步:對協方差矩陣作特征值分解 %獲得協方差矩陣的特征值的對角矩陣D [V,D]=eig(covMatrix); %取對角矩陣的特征值 featureValue=diag(D); %對特征值進行從大到小的排序 bigToSmall=sort(featureValue,'descend'); %第四步:取最大的d個特征值所對應的特征向量 %這里通過能量確定d的取值 d=0;%d的初始取值為0 someEnergy=0;%前項的能量 allEnergy=sum(bigToSmall(:));%所有的特征能量 while(someEnergy/allEnergy<0.9)d=d+1;someEnergy=sum(bigToSmall(1:d,:)); end %尋找特征值對應的特征向量 featureVector=zeros(10000,1); for i=1:dnowNumber=bigToSmall(i);%從大到小找到此時的值[row,column]=find(D==nowNumber);%在原來的特征值數組中定位findVector=V(:,column);%根據原來的特征值數組位置找到其對應的特征向量featureVector=[featureVector findVector]; end featureVector=featureVector(:,2:d+1);%刪掉之前添加的數據 %第五步:將原樣本矩陣與投影矩陣相乘即為降維后的數據集 %specialFace=oriFace*featureVector; %將會生成多張特征臉,這里要將矩陣的每一列重新合成一張照片 %由于生成時間慢,這里可以把圖片保存下來 for i=1:dname=strcat('featureFace',num2str(i),'.bmp');pic=featureVector(:,i);picToOri=reshape(pic,100,100);imwrite(picToOri,name);%保存圖片 end end

關于PCA算法中求特征向量的思考

找尋簡單的求特征向量的方法:
在PCA算法的過程中,其中有一個步驟是生成樣本的協方差矩陣,如果采用原始方法直接生成它的協方差矩陣的話,那么計算量將非常大,我在這里測試了一下,改改需要十多分鐘到二十分鐘左右。而能否有簡單的辦法呢?
在這里涉及到數學上的轉化:可以通過其他辦法得到原始協方差矩陣生成的特征向量。原始樣本協方差矩陣為C=AA’(此實驗中將生成1000010000的矩陣),而用C=A’A(此實驗中將生成3232的矩陣)也可以得到對應的特征向量,為A*ei,而整個過程得到的矩陣大小大大減小,計算量也是大大減小。證明如下:


其中,ei是C’=ΦTΦ的第i個特征向量,vi是C=ΦΦT的第i個特征向量,由證明可以看到,vi=Φei。所以通過求解C’=ΦTΦ的特征值分解得到ei,再左乘Φ就得到C=ΦΦT的特征向量vi了。也就是我們想要的特征臉。

function [] = annotherPCA() [averFace,oriFace]=averageFace(32,'s','.bmp'); averFace=averFace(:);%轉成一列 oriFace=double(oriFace); for i=1:32oriFace(:,i)=oriFace(:,i)-averFace; end %第二步:計算樣本的協方差矩陣 covMatrix=oriFace'*oriFace; %第三步:對協方差矩陣作特征值分解 %獲得協方差矩陣的特征值的對角矩陣D [V,D]=eig(covMatrix); %取對角矩陣的特征值 featureValue=diag(D); %對特征值進行從大到小的排序 bigToSmall=sort(featureValue,'descend'); %第四步:取最大的d個特征值所對應的特征向量 %這里通過能量確定d的取值 d=0;%d的初始取值為0 someEnergy=0;%前項的能量 allEnergy=sum(bigToSmall(:));%所有的特征能量 while(someEnergy/allEnergy<0.9)d=d+1;someEnergy=sum(bigToSmall(1:d,:)); end %尋找特征值對應的特征向量 featureVector=zeros(10000,1); for i=1:dnowNumber=bigToSmall(i);%從大到小找到此時的值featureVector=[featureVector oriFace*nowNumber]; end featureVector=featureVector(:,2:d+1);%刪掉之前添加的數據 %第五步:將原樣本矩陣與投影矩陣相乘即為降維后的數據集 %specialFace=oriFace*featureVector; %將會生成多張特征臉,這里要將矩陣的每一列重新合成一張照片 for i=1:dname=strcat('32featureFace',num2str(i),'.bmp');pic=featureVector(:,i);picToOri=reshape(pic,100,100);imwrite(picToOri,name);%保存圖片 end

問題:
使用兩種方法生成的特征臉卻不一樣?不由地思考到:原本是1000010000的矩陣,應該能夠得到10000個特征值和特征向量,但是使用簡化的辦法的話,生成3232的矩陣,只能得到32個特征值和特征向量,那么能否保證最大特征值保留下來了?在10000個特征值中得到的對應的最大的幾個特征向量被保留在了32個特征值對應的特征向量中了嘛?根據生成的特征臉不同,

可以初步斷定是沒有的。所以我覺得這種辦法只能夠生成特征臉,但是這個特征臉并不是最大的幾個特征值對應的特征向量所生成的,所以這應該得不到最優解。

結果展示

  • 實驗生成的平均臉:根據每一維的特征取平均值生成

    2.平均臉的數據集

    3.界面展示

    4.生成特征臉(用了兩種求特征向量的方法,之前的思考中有具體介紹)

  • 總結

    以上是生活随笔為你收集整理的基于PCA算法生成平均脸的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。