PCA在高光譜圖像中的應用

PCA介紹

主成分分析 (Principal Component Analysis ,簡稱 PCA)是最常用的一種降維方法。

算法介紹在這裏插入圖片描述

代碼

function [p_d_mat,project_mat,allmean]=PCA2(initialize_mat,p)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%輸入:
     %  initialize_mat: 原高維矩陣 m*n  m代表特徵 n代表樣本數
     %  p: 要求降維後矩陣的維數
%輸出:
     %p_d_mat: 降維後的p維矩陣
     %project_mat: 投影矩陣
     %allmean: 均值
%%%%%%%%%%%%%%%%%%%%%%%% by LiSR %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     %關於PCA2(initialize_mat,p)處理函數的說明
     %1、對initialize_mat每一個特徵維度求均值,然後減去均值得meanmat
     %2、對meanmat'*meanmat求特徵向量與特徵值
     %3、找出最大的特徵值與特徵向量,計算投影矩陣,project_mat=meanmat*max_v/sqrt(sigma) (爲了特徵向量單位陣)
     %4、計算降維後的矩陣  p_d_mat=project_mat'*meanmat;
     %5、除以p_d_mat矩陣最大的奇異值
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%     
    [features,rows]=size(initialize_mat);%原矩陣的特徵(維)數,和列數 size返回行與列
    allmean=mean(initialize_mat,2);%按列求原矩陣的均值 2代表按列求均值
    meanmat=zeros(features,rows);%初始化均值矩陣
    
    %計算差值,原矩陣所有列減去均值
    for i=1:rows  
        meanmat(:,i)=initialize_mat(:,i)-allmean;
    end
    
    %利用差值矩陣構建協方差矩陣,即C=meanmat*meanmat';
    %然後計算C的特徵值和特徵向量。由於C的維數過大,計算代價太大,
    %利用奇異值分解原理求得協方差矩陣C=meanmat*meanmat'的特徵值和特徵向量
    %即,利用求meanmat'*meanmat的特徵值、向量求原協方差矩陣meanmat*meanmat'
    %的特徵值和特徵向量
    %[U,S,V]=svd(meanmat)
    
    %注:Matlab中,求解出來的特徵值是默認從大到小排序了的,而自然的,特徵向量也是與排序後特徵值相對應的。
    [v,smat]=eig(meanmat'*meanmat);%求得特徵向量所組成的v矩陣和特徵值
    %把特徵值取出,放到數組中,按升序排列
    w=1:rows;
    for i=1:rows
        w(i)=smat(i,i);
    end
    
    project_mat=zeros(features,p);%初始化投影矩陣
    max_v=v(:,rows-p+1:rows); %取最大的特徵值對應的特徵向量
    %計算奇異值
    sigma=sqrt(w(rows-p+1:rows));
    %計算投影矩陣,U_i=A*V_i/sqrt(sigma)  對其歸一化
    for i=1:p
        project_mat(:,i)=meanmat*max_v(:,i)/sigma(i);
    end
    %計算降維後的矩陣
    p_d_mat=project_mat'*meanmat;
    %L_2 歸一  norm->返回A的最大奇異值,即max(svd(A))
    for i=1:size(p_d_mat,2)
        p_d_mat(:,i)=p_d_mat(:,i)/norm(p_d_mat(:,i));                      %假設A是一個矩陣,那麼norm(A)或者norm(A,2)計算的就是A的2範數;
    end
end

主函數

%pca+svm測試
%% a litte clean work

close all;
clear;
clc;
format compact;
%% load data 加載PaviaU數據集
%數據說明:訓練集共有1800個樣本,測試集有900個樣本
%數據樣本共有9種地表類型
load('PaviaU_gt.mat');
load('PaviaU.mat');

clsCnt = 9;
trnNum = 200;
%轉化成svm訓練所需要的格式
train_x = [];
train_y = [];
test_x = [];
test_y = [];
mm = max(max(max(paviaU)));
for i = 1 :clsCnt
    temp = getpixel(paviaU,paviaU_gt,i);
    clsNum = size(temp,1);
    %trnNum = ceil(clsNum*trnPer);
    tstNum = clsNum - trnNum;
    
    train_x = [ train_x ; temp(1:trnNum,:) ];
    cls_lab = zeros(trnNum,1);
    cls_lab(:,1) = i;
    train_y = [ train_y ; cls_lab];
    
    test_x = [ test_x ; temp(trnNum+1:trnNum+100,:) ];
    cls_lab = zeros(100,1);
    cls_lab(:,1) = i;
    test_y = [ test_y ; cls_lab];
    
end

    %首先求取特徵數
    feature_num=size(train_x,2);
    %準確度記錄
    Accuracy_record_train = [];
    Accuracy_record_test = [];
%從103個特徵中選取1~103個特徵
for num=1:20
    tic    
    %分別是訓練集與測試集以及相應的標籤
    traindata = double(train_x/mm);
    testdata  = double(test_x/mm);
    trainlabel=train_y;
    testlabel=test_y;

%% 進行pca數據預處理

    fprintf('iter %d',num);
    %兩種計算PCA的方法
     [traindata_pca,project_mat,allmean]=PCA_mine(traindata',num);
    
  
      
    test_samples=size(testdata,1);
    for i=1:test_samples  
        testdata_meanmat(:,i)=testdata(i,:)-allmean';                      %testdata 103*1
    end
    testdata_pca=project_mat'*testdata_meanmat;
    
    % 利用訓練集合建立分類模型
    %-s 代表svm類型  
    %-t代表 核函數類型
    %-c 設置C-SVC epsilon-SVR n-SVR懲罰參數 默認爲1
    %-g 設置核函數中 gamma的值

    %model = svmtrain(trainlabel,traindata,'-s 0 -t 2 -c 1.2 -g 2.8');
    %model = svmtrain(trainlabel,traindata,'-s 0 -t 1 -c 1.2 -g 2.8');
    model = svmtrain(trainlabel,traindata_pca','-s 0 -t 1 -c 1.2 -g 2.8');

    % 利用建立的svm模型看其在訓練集合上的分類效果
    [ptrain,acctrain,dec_values1] = svmpredict(trainlabel,traindata_pca',model);

    % 預測測試集合標籤
    [ptest,acctest,dec_values2] = svmpredict(testlabel,testdata_pca',model);
    
    %記錄準確度
    Accuracy_record_train=[Accuracy_record_train,acctrain(1)];
    Accuracy_record_test=[Accuracy_record_test,acctest(1)];
    
%%
toc;
end
%% 繪製測試集 訓練集準確度曲線
x = 1:1:20;
%x = 1:1:feature_num;
%y = sin(x);
plot(x,Accuracy_record_train)
hold on
y2 = cos(x);
plot(x,Accuracy_record_test,'r:')
grid on
xlabel('pca降維後的特徵數')
ylabel('準確度')
%axis([xmin xmax ymin ymax]);                                              % 設置座標軸在指定的區間
%legend('訓練集準確度','測試集準確度')                                       %爲圖片添加圖例
title('pca降維後的特徵數與svm分類準確度的關係示意圖')                         %添加圖像標題
text(1.5,0.3,'測試集準確度')                                                %將'測試集準確度'這個註解加到座標中的某個位置
gtext('測試集準確度')                                                       % 用鼠標的光標定位,將'測試集準確度'這個註解放在你鼠標點擊的地方
text(1.5,0.3,'訓練集準確度')                                                %將'測試集準確度'這個註解加到座標中的某個位置
gtext('訓練集準確度')                                                       % 用鼠標的光標定位,將'測試集準確度'這個註解放在你鼠標點擊的地方
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章