LDA算法-matlab代碼實現

本文使用LDA作爲分類器在matlab下做實驗。

  其中投影轉換矩陣W按照LDA的經典理論生成,如下的LDA函數,並返回各個類的投影后的(k-1)維的類均值。

LDA.m代碼如下:

複製代碼
function [W,centers]=LDA(Input,Target) % Ipuut: n*d matrix,each row is a sample; % Target: n*1 matrix,each is the class label % W: d*(k-1) matrix,to project samples to (k-1) dimention % cneters: k*(k-1) matrix,the means of each after projection % 初始化 [n dim]=size(Input); ClassLabel=unique(Target); k=length(ClassLabel); nGroup=NaN(k,1); % group count GroupMean=NaN(k,dim); % the mean of each value W=NaN(k-1,dim); % the final transfer matrix centers=zeros(k,k-1); % the centers of mean after projection SB=zeros(dim,dim); % 類間離散度矩陣 SW=zeros(dim,dim); % 類內離散度矩陣 % 計算類內離散度矩陣和類間離散度矩陣 for i=1:k group=(Target==ClassLabel(i)); nGroup(i)=sum(double(group)); GroupMean(i,:)=mean(Input(group,:)); tmp=zeros(dim,dim); for j=1:n if group(j)==1 t=Input(j,:)-GroupMean(i,:); tmp=tmp+t'*t; end end SW=SW+tmp; end m=mean(GroupMean); for i=1:k tmp=GroupMean(i,:)-m; SB=SB+nGroup(i)*tmp'*tmp; end % % W 變換矩陣由v的最大的K-1個特徵值所對應的特徵向量構成 % v=inv(SW)*SB; % [evec,eval]=eig(v); % [x,d]=cdf2rdf(evec,eval); % W=v(:,1:k-1); % 通過SVD也可以求得 % 對K=(Hb,Hw)'進行奇異值分解可以轉換爲對Ht進行奇異值分解.P再通過K,U,sigmak求出來 % [P,sigmak,U]=svd(K,'econ');=>[U,sigmak,V]=svd(Ht,0); [U,sigmak,V]=svd(SW,0); t=rank(SW); R=sigmak(1:t,1:t); P=SB'*U(:,1:t)*inv(R); [Q,sigmaa,W]=svd(P(1:k,1:t)) Y(:,1:t)=U(:,1:t)*inv(R)*W; W=Y(:,1:k-1); % 計算投影后的中心值 for i=1:k group=(Target==ClassLabel(i)); centers(i,:)=mean(Input(group,:)*W); end
複製代碼

  因爲LDA是二類分類器,需要推廣到多類的問題。常用的方法one-vs-all方法訓練K個分類器(這個方法在綜合時不知道怎麼處理?),以及任意兩個分類配對訓練分離器最後得到k(k-1)/2個的二類分類器。本文采用訓練後者對樣本進行訓練得到模型model。在代碼中,model爲數組struct。

用於訓練的函數LDATraining.m

複製代碼
function [model,k,ClassLabel]=LDATraining(input,target) % input: n*d matrix,representing samples % target: n*1 matrix,class label % model: struct type(see codes below) % k: the total class number % ClassLabel: the class name of each class % model=struct; [n dim]=size(input); ClassLabel=unique(target); k=length(ClassLabel); t=1; for i=1:k-1 for j=i+1:k model(t).a=i; model(t).b=j; g1=(target==ClassLabel(i)); g2=(target==ClassLabel(j)); tmp1=input(g1,:); tmp2=input(g2,:); in=[tmp1;tmp2]; out=ones(size(in,1),1); out(1:size(tmp1,1))=0; % tmp3=target(g1); % tmp4=target(g2); % tmp3=repmat(tmp3,length(tmp3),1); % tmp4=repmat(tmp4,length(tmp4),1); % out=[tmp3;tmp4]; [w m]=LDA(in,out); model(t).W=w; model(t).means=m; t=t+1; end end
複製代碼

  在預測時,使用訓練時生成的模型進行k(k-1)/2次預測,最後選擇最多的分類作爲預測結果。在處理二類分類器預測時,通過對預測樣本作W的投影變換再比較與兩個類的均值進行比較得到(不知道有沒有更好的辦法?)

用於預測的函數LDATesting.m

複製代碼
function target=LDATesting(input,k,model,ClassLabel) % input: n*d matrix,representing samples % target: n*1 matrix,class label % model: struct type(see codes below) % k: the total class number % ClassLabel: the class name of each class [n dim]=size(input); s=zeros(n,k); target=zeros(n,1); for j=1:k*(k-1)/2 a=model(j).a; b=model(j).b; w=model(j).W; m=model(j).means; for i=1:n sample=input(i,:); tmp=sample*w; if norm(tmp-m(1,:))<norm(tmp-m(2,:)) s(i,a)=s(i,a)+1; else s(i,b)=s(i,b)+1; end end end for i=1:n pos=1; maxV=0; for j=1:k if s(i,j)>maxV maxV=s(i,j); pos=j; end end target(i)=ClassLabel(pos); end
複製代碼

示例代碼爲:

function target=test(in,out,t) [model,k,ClassLabel]=LDATraining(in,out); target=LDATesting(t,k,model,ClassLabel);

  實驗中對USPS數據集進行了測試,效果不怎麼好,正確率才39%左右,而這個數據集使用KNN算法可以達到百分之百九十的正確率,汗!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章