function multiAdaboostStruct = multiAdaboostTrain(TrainData, nSampPerClass,nClass)
%function multiAdaboostStruct = multiAdaboostTrain(TrainData, nSampPerClass)
% 采用1对1投票策略将 Adaboost 推广至多类问题的训练过程,将多类Adaboost训练结果保存至multiAdaboostStruct中
%
% 输入:--TrainData:每行是一个样本人脸
% --nClass:人数,即类别数
% --nSampPerClass:nClass*1维的向量,记录每类的样本数目,如 nSampPerClass(iClass)
% 给出了第iClass类的样本数目
%
% 输出:--multiAdaboostStruct:一个包含多类Adaboost训练结果的结构体
%开始训练,需要计算每两类间的分类超平面,共(nClass-1)*nClass/2个
for ii=1:(nClass-1)
for jj=(ii+1):nClass
clear X;
clear Y;
startPosII = sum( nSampPerClass(1:ii-1) ) + 1;
endPosII = startPosII + nSampPerClass(ii) - 1;
X(1:nSampPerClass(ii), :) = TrainData(startPosII:endPosII, :);
startPosJJ = sum( nSampPerClass(1:jj-1) ) + 1;
endPosJJ = startPosJJ + nSampPerClass(jj) - 1;
X(nSampPerClass(ii)+1:nSampPerClass(ii)+nSampPerClass(jj), :) = TrainData(startPosJJ:endPosJJ, :);
% 设定两两分类时的类标签
Y = ones(nSampPerClass(ii) + nSampPerClass(jj), 1)+1;
Y(nSampPerClass(ii)+1:nSampPerClass(ii)+nSampPerClass(jj)) = 1;
% 第ii个人和第jj个人两两分类时的分类器结构信息
AdaboostStruct{ii}{jj}=ADABOOST_tr(@threshold_tr,@threshold_te, X, Y, 20);%进行20次迭代
end
end
% 已学得的分类结果
multiAdaboostStruct.AdaboostStruct = AdaboostStruct;
multiAdaboostStruct.nClass = nClass;
function class = multiAdaboostClassify(TestFace, multiAdaboostStruct)
% 输入:--TestFace:测试样本集。m*n 的2维矩阵,每行一个测试样本
% --multiAdaboostStruct:多类Adaboost的训练结果,由函数 multiAdaboostTrain 返回,默认是从Mat/multiAdaboostTrain.mat文件中读取
%
% 输出:--class: m*1 列向量,对应 TestFace 的类标签
% 读入训练结果
if nargin < 2
t = dir('Mat/multiAdaboostTrain.mat');
if length(t) == 0
error('没有找到训练结果文件,请在分类以前首先进行训练!');
end
load('Mat/multiAdaboostTrain.mat');
end
nClass = multiAdaboostStruct.nClass; % 读入类别数
AdaboostStruct = multiAdaboostStruct.AdaboostStruct; % 读入两两类之间的信息
%%%%%%%%%%%%%%%%%%%%%%%% 投票策略解决多类问题 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
m = size(TestFace, 1);
Voting = zeros(m, nClass); % m个测试样本,每个样本nPerson 个类别的投票箱
for iIndex = 1:nClass-1
for jIndex = iIndex+1:nClass
classes=ADABOOST_te(AdaboostStruct{iIndex}{jIndex},@threshold_te,TestFace);
% 投票
Voting(:, iIndex) = Voting(:, iIndex) + (classes == 2);
Voting(:, jIndex) = Voting(:, jIndex) + (classes == 1);
end % for jClass
end % for iClass
% final decision by voting result
[vecMaxVal, class] = max( Voting, [], 2 );
%display(sprintf('TestFace对应的类别是:%d',class));
训练样本
function train(C, gamma)
% 整个训练过程,包括读入图像,PCA降维以及多类 SVM 训练,各个阶段的处理结果分别保存至文件:
% 将 PCA 变换矩阵 W 保存至 Mat/PCA.mat
% 将 scaling 的各维上、下界信息保存至 Mat/scaling.mat
% 将 PCA 降维并且 scaling 后的数据保存至 Mat/trainData.mat
% 将多类 Adaboost 的训练信息保存至 Mat/multiAdaboostTrain.mat
global imgRow;
global imgCol;
global SVM;
global Adaboost;
display(' ');
display(' ');
display('训练开始...');
nPerson=40;
nFacesPerPerson = 5;
display('读入人脸数据...');
[imgRow,imgCol,FaceContainer,faceLabel]=ReadFaces(nFacesPerPerson,nPerson);
display('..............................');
nFaces=size(FaceContainer,1);%样本(人脸)数目
display('PCA降维...');
[pcaFaces, W] = fastPCA(FaceContainer, 20); % 主成分分析PCA
% pcaFaces是200*20的矩阵, 每一行代表一张主成分脸(共40人,每人5张),每个脸20个维特征
% W是分离变换矩阵, 10304*20 的矩阵
visualize_pc(W);%显示主成分脸
display('..............................');
X = pcaFaces;
display('归一化开始...');
display('.........');
[X,A0,B0] = scaling(X);
save('Mat/scaling.mat', 'A0', 'B0');
% 保存 scaling 后的训练数据至 trainData.mat
TrainData = X;
trainLabel = faceLabel;
save('Mat/trainData.mat', 'TrainData', 'trainLabel');
display('归一化完成...');
display('训练分类器开始,这个过程可能会花上几分钟.........................');
for iPerson = 1:nPerson
nSplPerClass(iPerson) = sum( (trainLabel == iPerson) );
end
multiAdaboostStruct = multiAdaboostTrain(TrainData, nSplPerClass ,nPerson);
display('正在保存Adaboost训练结果...');
save('Mat/multiAdaboostTrain.mat', 'multiAdaboostStruct');
display('..............................');
display('训练完成。');
测试过程
function test()
% 测试对于整个测试集的识别率
%
% 输出:accuracy --- 对于测试集合的识别率
global SVM;
global Adaboost;
display(' ');
display(' ');
display('测试开始...');
nFacesPerPerson = 5;
nPerson = 40;
bTest = 1;
% 读入测试集合
display('读入测试集合...');
[imgRow,imgCol,TestFace,testLabel] = ReadFaces(nFacesPerPerson, nPerson, bTest);
display('..............................');
% 读入相关训练结果
display('载入训练参数...');
load('Mat/PCA.mat');
load('Mat/scaling.mat');
load('Mat/trainData.mat');
load('Mat/multiAdaboostTrain.mat');
display('..............................');
% PCA降维
display('PCA降维处理...');
[m n] = size(TestFace);
TestFace = (TestFace-repmat(meanVec, m, 1))*V; % 经过pca变换降维
TestFace = scaling(TestFace,1,A0,B0);
display('..............................');
% 多类 AdaBoost 分类
display('测试集识别中...');
classes = multiAdaboostClassify(TestFace);
display('..............................');
% 计算识别率
nError = sum(classes ~= testLabel);
accuracy = 1 - nError/length(testLabel);
display(['PCA+Adaboost对于测试集200个人脸样本的识别率为', num2str(accuracy*100), '%']);
识别主要代码
function nClass = classify(newFacePath)
% 整个分类(识别)过程
global SVM;
global Adaboost;
display(' ');
display(' ');
display('识别开始...');
% 读入相关训练结果
display('载入训练参数...');
load('Mat/PCA.mat');
load('Mat/scaling.mat');
load('Mat/trainData.mat');
load('Mat/multiAdaboostTrain.mat');
display('..............................');
xNewFace = ReadAFace(newFacePath); % 读入一个测试样本
xNewFace = double(xNewFace);
xNewFace = (xNewFace-meanVec)*V;% 经过pca变换降维
xNewFace = scaling(xNewFace,1,A0,B0);
display('身份识别中...');
nClass = multiAdaboostClassify(xNewFace);
display('..............................');
display(['身份识别结束,类别为:' num2str(nClass), '。']);