机器学习——PCA(主成分分析)与人脸识别
目錄
系列文章目錄
一、PCA的概念與原理
1.PCA簡介
2.PCA算法模型
二、PCA運用于人臉識別
1.預處理
1.1 數據導入與處理
1.2 數據集求均值與數據中心化
1.3?求協方差矩陣、特征值與特征向量并排序
2.人臉重構
3.人臉識別
4.人臉圖像降維與可視化
5.其他
5.1 內部函數定義
5.2 數據集及資源
總結
系列文章目錄
本系列博客重點在機器學習的概念原理與代碼實踐,不包含繁瑣的數學推導(有問題歡迎在評論區討論指出,或直接私信聯系我)。
代碼可以全抄? ??大家搞懂原理與流程去復現才是有意義的!!!
第一章 PCA與人臉識別
梗概
本篇博客主要介紹PCA(主成分分析)算法并將PCA用于人臉的重構、識別、圖像降維可視化(內附數據集與matlab代碼)
一、PCA的概念與原理
1.PCA簡介
PCA(主成分分析)為主流的一種線性降維算法。以”最小重構誤差“為目標導向,通過降維(投影),用數據中相對重要(最主要)的信息表達(代替)原數據,從而達到降維的目的。
2.PCA算法模型
經典的PCA解決問題可劃分為以下步驟
① 數據的導入與處理(eg.人臉識別中需要將每一張人臉拉成一列或一行)
② 計算數據均值并對數據中心化
③ 計算協方差矩陣(散度矩陣)
④ 分解協方差矩陣得到按特征值從大到小排序的特征向量(也可用SVD分解)
⑤ 取出前k個特征向量作為投影,使原數據降維到對應投影方向,實現由原本n維數據降到k維
二、PCA運用于人臉識別
1.預處理
Tips:預處理包括數據導入處理、求均值去心化、分解協方差矩陣得到特征向量(特征臉)
1.1 數據導入與處理
利用imread批量導入人臉數據庫,或直接load相應mat文件,并在導入時不斷將人臉拉成一個個列向量組成reshaped_faces,本實驗取出每個人的前30%作為測試數據,后70%作為訓練數據。
clear; % 1.人臉數據集的導入與數據處理(400張圖,一共40人,一人10張) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% reshaped_faces=[]; for i=1:40 ? ?for j=1:10 ? ? ??if(i<10)a=imread(strcat('C:\AR_Gray_50by40\AR00',num2str(i),'-',num2str(j),'.tif')); ? ??elsea=imread(strcat('C:\AR_Gray_50by40\AR0',num2str(i),'-',num2str(j),'.tif')); ?end ? ? ? ? ?b = reshape(a,2000,1); %將每一張人臉拉成列向量b=double(b); %utf-8轉換為double類型,避免人臉展示時全灰的影響? ? ? ?reshaped_faces=[reshaped_faces, b]; ?end end% 取出前30%作為測試數據,剩下70%作為訓練數據 test_data_index = []; train_data_index = []; for i=0:39test_data_index = [test_data_index 10*i+1:10*i+3];train_data_index = [train_data_index 10*i+4:10*(i+1)]; endtrain_data = reshaped_faces(:,train_data_index); test_data = reshaped_faces(:, test_data_index);1.2 數據集求均值與數據中心化
利用mean函數對訓練集求平均值,得出平均臉(如圖1),將訓練集中所有數據減去平均臉,實現中心化(中心化后某些人臉如圖2,相對原圖灰度值更低)。
% 2.圖像求均值,中心化 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 求平均臉 mean_face = mean(train_data,2); %waitfor(show_face(mean_face)); %平均臉展示,測試用% 中心化 centered_face = (train_data - mean_face); %用于展示中心化后某些訓練圖片 測試用 %waitfor(show_faces(centered_face));圖1 AR數據集中的平均臉
圖2 中心化后的部分人臉?
1.3?求協方差矩陣、特征值與特征向量并排序
根據數學推導,協方差矩陣可由cov_matrix = centered_face(中心化人臉數據集) * centered_face'求得,再利用eig函數基于特征值對協方差矩陣進行分解(或使用SVD),并用sort函數將特征向量按從大到小排序好,得到所有特征臉(部分特征臉如圖3)。
% 3.求協方差矩陣、特征值與特征向量并排序 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 協方差矩陣 cov_matrix = centered_face * centered_face'; [eigen_vectors, dianogol_matrix] = eig(cov_matrix);% 從對角矩陣獲取特征值 eigen_values = diag(dianogol_matrix);% 對特征值按索引進行從大到小排序 [sorted_eigen_values, index] = sort(eigen_values, 'descend');?% 獲取排序后的征值對應的特征向量 sorted_eigen_vectors = eigen_vectors(:, index);% 特征臉(所有) all_eigen_faces = sorted_eigen_vectors;%用于展示某些特征臉 測試用 waitfor(show_faces(all_eigen_faces));圖3 部分特征臉(eigenface)
Tips:一個特征臉即一個特征向量,數據集中所有人臉都是由某些特征臉組合得到,故利用特征向量(特征臉)是后續實現人臉重構、識別、降維可視化的關鍵。
2.人臉重構
重構的意義:檢測特征臉對人臉的還原度與維數的關系(數據降到多少維才能較好還原原始數據)
從已中心化的centered_faces中取出某人臉,用20,40,60,80,...,160個投影(前n個特征向量)按公式rebuild_face = eigen_faces * (eigen_faces' * single_face) + mean_face來重構此人臉,并觀察在不同數量的投影下的還原度,重構效果如圖4。
%%人臉重構% 取出第一個人的人臉,用于重構 single_face = centered_face(:,1);index = 1; for dimensionality=20:20:160% 取出相應數量特征臉(前n大的特征向量,用于重構人臉)eigen_faces = all_eigen_faces(:,1:dimensionality);% 重建人臉并顯示rebuild_face = eigen_faces * (eigen_faces' * single_face) + mean_face;subplot(2, 4, index); %兩行四列index = index + 1;fig = show_face(rebuild_face);title(sprintf("dimensionality=%d", dimensionality)); ? ?if (dimensionality == 160)waitfor(fig);end end圖4 不同維度下人臉還原(重構)效果?
3.人臉識別
Tips:本實驗中有兩個變量,k從1~6取值,維度從10~160,探究k值及維度對識別率的共同影響
分別對測試集、訓練集進行降維,將人臉投影到10,20,30,…,160維空間中,計算未知人臉與所有已知人臉的距離(歐幾里得距離),然后使用最近鄰分類器KNN進行識別(共同影響如圖5 只考慮維度影響如圖6 橫坐標為維度/10)
% 5.人臉識別 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%index = 1; Y = []; % KNN for k=1:6for i=10:10:160% 取出相應數量特征臉eigen_faces = all_eigen_faces(:,1:i);% 測試、訓練數據降維projected_train_data = eigen_faces' * (train_data - mean_face);projected_test_data = eigen_faces' * (test_data - mean_face);% 用于保存最小的k個值的矩陣% 用于保存最小k個值對應的人標簽的矩陣minimun_k_values = zeros(k,1);label_of_minimun_k_values = zeros(k,1);% 測試臉的數量test_face_number = size(projected_test_data, 2);% 識別正確數量correct_predict_number = 0;% 遍歷每一個待測試人臉for each_test_face_index = 1:test_face_numbereach_test_face = projected_test_data(:,each_test_face_index);% 先把k個值填滿,避免在迭代中反復判斷for each_train_face_index = 1:kminimun_k_values(each_train_face_index,1) = norm(each_test_face - projected_train_data(:,each_train_face_index));label_of_minimun_k_values(each_train_face_index,1) = floor((train_data_index(1,each_train_face_index) - 1) / 10) + 1;end% 找出k個值中最大值及其下標[max_value, index_of_max_value] = max(minimun_k_values);% 計算與剩余每一個已知人臉的距離for each_train_face_index = k+1:size(projected_train_data,2)% 計算距離distance = norm(each_test_face - projected_train_data(:,each_train_face_index));% 遇到更小的距離就更新距離和標簽if (distance < max_value)minimun_k_values(index_of_max_value,1) = distance;label_of_minimun_k_values(index_of_max_value,1) = floor((train_data_index(1,each_train_face_index) - 1) / 10) + 1;[max_value, index_of_max_value] = max(minimun_k_values);endend% 最終得到距離最小的k個值以及對應的標簽% 取出出現次數最多的值,為預測的人臉標簽predict_label = mode(label_of_minimun_k_values);real_label = floor((test_data_index(1,each_test_face_index) - 1) / 10)+1;if (predict_label == real_label)%fprintf("預測值:%d,實際值:%d,正確\n",predict_label,real_label);correct_predict_number = correct_predict_number + 1;else%fprintf("預測值:%d,實際值:%d,錯誤\n",predict_label,real_label);endend% 單次識別率correct_rate = correct_predict_number/test_face_number;Y = [Y correct_rate];fprintf("k=%d,i=%d,總測試樣本:%d,正確數:%d,正確率:%1f\n", k, i,test_face_number,correct_predict_number,correct_rate);end end % 求不同k值不同維度下的人臉識別率及平均識別率 Y = reshape(Y,k,16); waitfor(waterfall(Y)); avg_correct_rate=mean(Y); waitfor(plot(avg_correct_rate));?圖5 不同k值與維度下PCA的人臉識別率
??圖6?不同維度下PCA的人臉識別率(橫坐標為維度/10)
4.人臉圖像降維與可視化
取出對應數量的特征臉(n維取n個),利用公式projected_test_data = eigen_faces' * (test_data - mean_face)對測試集或其他子集進行投影,投影后上色(同人同色)并使用scatter畫圖實現可視化(二維人臉分布如圖7,三維人臉分布如圖8)。
Tips:本實驗以測試集的二三維可視化為例
% 6.人臉數據二三維可視化(可推廣到不同數據集) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%for i=[2 3]% 取出相應數量特征臉eigen_faces = all_eigen_faces(:,1:i);% 投影projected_test_data = eigen_faces' * (test_data - mean_face);color = [];for j=1:120color = [color floor((j-1)/4)*5];end% 顯示if (i == 2)waitfor(scatter(projected_test_data(1, :), projected_test_data(2, :), [], color));elsewaitfor(scatter3(projected_test_data(1, :), projected_test_data(2, :), projected_test_data(3, :), [], color));endend圖7 測試集降維至二維圖像分布
?圖8?測試集降維至三維圖像分布
5.其他
5.1 內部函數定義
本實驗中將人臉圖像展示抽象為函數,函數定義如下:
%內用函數定義 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 輸入向量,顯示臉 function fig = show_face(vector)fig = imshow(mat2gray(reshape(vector, [50, 40]))); end% 顯示矩陣中某些臉 function fig = show_faces(eigen_vectors)count = 1;index_of_image_to_show = [1,5,10,15,20,30,50,70,100,150];for i=index_of_image_to_showsubplot(2,5,count);fig = show_face(eigen_vectors(:, i));title(sprintf("i=%d", i));count = count + 1;end end5.2 數據集及資源
本實驗以AR50_40數據集做展示,代碼可適用多個數據集。
常用人臉數據集如下(不要白嫖哈哈哈)
鏈接:https://pan.baidu.com/s/12Le0mKEquGMgh5fhNagZGw?
提取碼:yrnb
PCA完整代碼:李憶如/憶如的機器學習 - Gitee.com
5.3 參考資料
1.賴志輝的課
2. PCA原理_PiggyGaGa的博客-CSDN博客_pca
3.基于 PCA 的人臉識別方法——特征臉法[2] - 知乎 (zhihu.com)
4.周志華《機器學習》
總結
PCA作為經典的線性降維算法,通過”最小重構誤差“為目標導向對數據進行投影實現降維,如今仍然在機器學習許多領域(語言圖像處理、數據可視化)有優異表現。但作為一種無監督學習方法(沒有對訓練樣本做標注),在對數據完全無知的情況下,PCA并不能得到較好的保留數據信息,且PCA對于主成分的分析判斷是影響實驗結果的重要因素(不好界定主要信息),另外,PCA對于非線性的數據降維效果較差,后續博客會分析其他算法優化或解決上述問題。
總結
以上是生活随笔為你收集整理的机器学习——PCA(主成分分析)与人脸识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql解题器_mysql触发器,答题
- 下一篇: 【数据结构教程 李春葆】上机实验--第一