PCA 实践 利用 PCA 算法对人脸数据集内所有人进行降维和特征提取 PCA原理解析+代码
數(shù)據(jù)集
實(shí)驗(yàn)所用到的數(shù)據(jù)集在下面的鏈接中, 這些數(shù)據(jù)是來自劍橋大學(xué)提供的 AT&T 人臉數(shù)據(jù)
集,有 40 個(gè)人的人臉圖像, 每個(gè)人有 10 張不同光照和姿態(tài)的照片。
樣例:
地址: http://www.cl.cam.ac.uk/Research/DTG/attarchive/pub/data/att_faces.tar.Z
實(shí)驗(yàn)內(nèi)容
加載數(shù)據(jù)集,利用 PCA 算法對(duì)數(shù)據(jù)集內(nèi)所有人進(jìn)行降維和特征提取,然后將得到的主
成分特征向量還原成圖像進(jìn)行觀察。這里可以嘗試采用不同的降維維度 K 進(jìn)行操作,分別觀
察不同 K 下的特征圖像。
實(shí)驗(yàn)拓展
嘗試對(duì)剛降維的特征圖像進(jìn)行 PCA 逆變換,觀察變換前后的圖像差異
?
數(shù)據(jù)集中包含了40個(gè)文件夾,對(duì)應(yīng)了40個(gè)志愿者人臉,每個(gè)文件夾中有一個(gè)志愿者的人臉的多種狀態(tài)。
??????
此處使用相對(duì)目錄,依次訪問每個(gè)子文件夾,通過在中間過程中輸出圖像的維度,我們觀察到圖像是112x92x3即,長寬分別為112,93,通道數(shù)為3。首先,我們先對(duì)圖像進(jìn)行灰度化處理,然后將圖像維度展開成為一列,存入列表。
圖像的height,width=112,92,X代表我們的數(shù)據(jù)集,是一個(gè)400x10304的向量;之所以是400x10304,是因?yàn)榭偣?00幅圖像,每個(gè)圖像是一個(gè)112x92的image,將圖像展開成一個(gè)一維向量,維度為1x10304,將400幅圖像組合得到一個(gè)400x10304的矩陣。其中Y是數(shù)據(jù)的標(biāo)簽。
此處,我們展示試著顯示一組圖像,在文件夾中選取每個(gè)子文件夾下的第一個(gè)圖像拼合顯示如下:
因?yàn)榇翱诖笮∠拗?#xff0c;此處并沒有顯示完全40副圖像。
其中,對(duì)10304個(gè)列向量做平均,即對(duì)400個(gè)人臉圖像的每一個(gè)對(duì)應(yīng)像素值做平均,計(jì)算均值,得到一個(gè)1x10304的向量。并將該向量重新轉(zhuǎn)化為和原圖像同樣大小的維度,然后顯示出來,如下:
注意,計(jì)算協(xié)方差矩陣之前,需要先將每個(gè)變量減去均值,得到中心化的向量,然后通過使用sklearn中的奇異值分解函數(shù),得到前K個(gè)特征向量。
不需要計(jì)算協(xié)方差矩陣S,同時(shí),在數(shù)值上更加精確,因?yàn)樵谟?jì)算機(jī)存儲(chǔ)中,可能會(huì)產(chǎn)生累計(jì)誤差。
我們?cè)O(shè)定閾值為0.95,計(jì)算保留的主成分?jǐn)?shù)量。計(jì)算代碼如下:
計(jì)算得到的K值為111,也就是說,前111個(gè)奇異值得到的結(jié)果已經(jīng)能代表90%的情況了,為方便處理,我們此處選取K=100.通過奇異值分解得到Kx10304的變換矩陣,我們可以得到如下十張主成分圖像:
注意:如果使用OpenCV中的imshow函數(shù)進(jìn)行顯示,需要先將數(shù)據(jù)轉(zhuǎn)換為np.unit8格式,同時(shí)范圍規(guī)范化到0-255的范圍(此處使用最大最小值歸一化),而使用matplotlib則不用進(jìn)行如此操作。
?
規(guī)范化及使用OpenCV顯示相關(guān)代碼
使用matplotlib顯示相關(guān)代碼:
當(dāng)完成主成分提取之后,我們對(duì)圖像進(jìn)行還原:
其中,U是變換矩陣,還原方式如下:
?????
????? 并輸出30張還原之后的圖像;如下:
???????? 我們可以看到,以上30張圖像分別對(duì)應(yīng)了原始數(shù)據(jù)集中的3個(gè)人的圖像,相比于原來的30張,如今還原得到的圖像丟失了一部分信息,不過不是非常明顯。
源代碼
1. import cv2 2. import tensorflow as tf 3. import numpy as np 4. import matplotlib.pyplot as plt 5. from sklearn.decomposition import TruncatedSVD 6. 7. FACE_PATH = "orl_faces" 8. PERSON_NUM = 40 9. PERSON_FACE_NUM = 10 10. K = 10 # Number of principle components 11. 12. raw_img = [] 13. data_set = [] 14. data_set_label = [] 15. 16. 17. def read_data(): 18. height = 0 19. width = 0 20. for i in range(1, PERSON_NUM + 1): 21. person_path = FACE_PATH + '/s' + str(i) 22. 23. for j in range(1, PERSON_FACE_NUM + 1): 24. img = cv2.imread(person_path + '/' + str(j) + '.pgm') 25. #print(img.shape) 112,92,3 26. if j == 1: 27. raw_img.append(img) 28. img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 29. height, width = img_gray.shape 30. #print(height,width) 31. img_col = img_gray.reshape(height * width) 32. data_set.append(img_col) 33. data_set_label.append(i) 34. 35. return height, width 36. 37. 38. # Import Data 39. height, width = read_data() 40. print(height,width) 41. X = np.array(data_set) 42. #print(X.shape) # 400*10304 43. Y = np.array(data_set_label) 44. #print(Y.shape) 45. n_sample, n_feature = X.shape 46. 47. # Print some samples 48. raw_img = np.hstack(raw_img) 49. cv2.namedWindow("Image") 50. cv2.imshow('Image', raw_img) 51. cv2.waitKey(1) 52. cv2.destroyAllWindows() 53. 54. # 計(jì)算均值 A preview of average_face 55. average_face = np.mean(X, axis=0) #對(duì)10304個(gè)列向量做平均 56. # for i in average_face: 57. # print(i) 58. #num+=1 59. fig = plt.figure() 60. plt.imshow(average_face.reshape((height, width)), cmap=plt.cm.gray) 61. plt.title("Average Face", size=12) 62. plt.xticks(()) 63. plt.yticks(())#不顯示橫縱坐標(biāo) 64. #plt.savefig("average_face.png") 65. plt.show() 66. 67. # Calculate 68. equalization_X = X - average_face #差值400*10304 69. #計(jì)算協(xié)方差矩陣 70. 71. covariance_X = np.cov(equalization_X.transpose()) 72. print(covariance_X.shape) 73. print(equalization_X.shape) 74. #特征值分解 使用sklearn中的SVD函數(shù)分解 75. svd = TruncatedSVD(n_components=K, random_state=44) 76. svd.fit(equalization_X) 77. 78. # total_variance, n_components = 0.0, 0 79. # for variance in svd.explained_variance_ratio_: 80. # total_variance += variance 81. # n_components += 1 82. # if total_variance > 0.95: break 83. 84. #print(n_components) 9 85. #print(svd.components_.shape) 10*10304 86. print(svd.components_.shape) 87. topk=np.zeros(svd.components_.shape) 88. # for i in range(K): 89. # #print(svd.components_[i]) 90. # topk[i]=255.0*(svd.components_[i]-np.min(svd.components_[i]))/\ 91. # (np.max(svd.components_[i])-np.min(svd.components_[i])) 92. #print(topk[i]) 93. # img=topk[1].reshape(height, width) 94. # img=img.astype(np.uint8) 95. # #print(img.shape) 96. # cv2.imshow('1',img) 97. # cv2.waitKey(0) 98. # cv2.destroyAllWindows() 99. #np.matmul(equalization_X,) 100. # topk=svd.components_+average_face 101. 102. 103. # 打印輸出前K個(gè)主成分臉 104. 105. plt.figure() 106. for i in range(1, K + 1): 107. plt.subplot(2, K/2, i) 108. #print(svd.components_[i-1].shape) 109. plt.imshow((svd.components_[i - 1]).reshape(height, width), cmap=plt.cm.gray) 110. #print(svd.components_[i - 1].reshape(height, width)) 111. plt.xticks(()) 112. plt.yticks(()) 113. plt.show() 114. 115. topk=average_face+np.matmul(equalization_X,np.matmul(svd.components_.T,svd.components_)) 116. print(topk.shape) 117. K=30 118. plt.figure() 119. for i in range(1, K + 1): 120. plt.subplot(5, K/5, i) 121. #print(svd.components_[i-1].shape) 122. plt.imshow((topk[i - 1]).reshape(height, width), cmap=plt.cm.gray) 123. #print(svd.components_[i - 1].reshape(height, width)) 124. plt.xticks(()) 125. plt.yticks(()) 126. plt.show()如不知道如何去掉行號(hào),參考個(gè)人博文中的解決方案。
總結(jié)
以上是生活随笔為你收集整理的PCA 实践 利用 PCA 算法对人脸数据集内所有人进行降维和特征提取 PCA原理解析+代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: chm文件打不开的问题
- 下一篇: 梳理百年深度学习发展史-七月在线机器学习