小言_互联网的博客

【numpy手写系列】用PCA、LDA、SVM与CNN手写人脸识别代码

278人阅读  评论(0)

引言

        目标在本课程项目中,学生将单独构建人脸识别系统系统学生需要应用主成分分析(PCA)来执行数据降维和可视化,以了解底层数据分布。然后,要求学生训练并应用三种分类模型——线性判别分析(LDA)、支持向量机(SVM)和卷积神经网络(CNN)–对人脸图像进行分类。通过该项目,学生有望获得基本的以及当前流行的模式识别技术的重要知识。编程语言学生可以在项目中使用他们选择的任何语言,尽管至少从MATLAB或Python开始。建议使用MATLAB,因为它提供了一个简单、完整的环境,以及可视化结果。特别是,可以在项目并在网上找到。


【numpy手写系列】用PCA、LDA、SVM与CNN手写人脸识别代码

引言

工作区文件结构

数据集

介绍

数据集获取方式: 

用于特征提取、可视化和分类的PCA

任务

实现代码

• PCA based data distribution visualization

• PCA plus nearest neighbor classifification results

结果

• PCA based data distribution visualization

• PCA plus nearest neighbor classifification results

用于特征提取和分类的LDA

任务

实现代码

结果

• LDA based data distribution visualization

• LDA plus nearest neighbor classifification results ​编辑

用于分类的SVM

任务

实现代码

结果

用于分类的神经网络

任务

 实现代码

结果


工作区文件结构

        请务必按照以下结构构建工作区域,取名请随意。


数据集

介绍

        项目将在CMU PIE数据集上进行,使用70%的所提供的图像用于训练,剩余的30%用于测试。PIE是一个人脸识别数据集,内含68个人,每个人有170张图片,随机抽样一个人取出2张图片看看:

数据集获取方式: 

提取码:3x2zhttps://pan.baidu.com/s/172uo2gLluo47wBTbn3LfHA%C2%A0


用于特征提取、可视化和分类的PCA

任务

       原始人脸图像的大小为32×32像素,因此每个图像的1024维矢量年龄从CMU PIE训练集中随机抽取500张图片和您自己的照片。应用PCA将矢量化图像的维数分别降低到2和3。可视化二维和三维绘图中的投影数据矢量。突出显示与照片还可视化用于降维的相应3个特征面。然后应用PCA将人脸图像的维数分别降低到40、80和200。使用最近邻规则对测试图像进行分类。报告分类准确性分别在CMU PIE测试图像和您自己的照片上。

实现代码

PCA based data distribution visualization


  
  1. import os
  2. from numpy import *
  3. import numpy as np
  4. import cv2
  5. import matplotlib.pyplot as plt
  6. from pylab import mpl
  7. def img2vector( im_path):
  8. im = cv2.imread(im_path, 0)
  9. rows, cols = im.shape
  10. imgVector = np.zeros(( 1, rows * cols))
  11. imgVector = np.reshape(im, ( 1, rows * cols))
  12. return imgVector
  13. def load_dataset( k):
  14. faceData_path = '../PIE'
  15. faceData_length = len(os.listdir(faceData_path))
  16. train_face = np.zeros((faceData_length * k, 32 * 32))
  17. train_label = np.zeros(faceData_length * k)
  18. test_face = np.zeros((faceData_length * ( 170 - k), 32 * 32))
  19. test_label = np.zeros(faceData_length * ( 170 - k))
  20. sample = random.permutation( 170) + 1
  21. for i in range(faceData_length):
  22. people_idx = i + 1
  23. if people_idx == 26:
  24. for j in range( 10):
  25. face_im_path = os.path.join(faceData_path, str(people_idx), str(j+ 1) + '.jpg')
  26. faceVector_im = img2vector(face_im_path)
  27. if j <= 7:
  28. train_face[i*k+j, :] = faceVector_im
  29. train_label[i*k + j] = people_idx
  30. else:
  31. test_face[i*( 170-k) + (j-k), :] = faceVector_im
  32. test_label[i*( 170-k) + (j-k)] = people_idx
  33. for j in range( 170):
  34. face_im_path = os.path.join(faceData_path, str(people_idx), str(sample[j]) + '.jpg')
  35. faceVector_im = img2vector(face_im_path)
  36. if j < k:
  37. train_face[i*k+j, :] = faceVector_im
  38. train_label[i*k + j] = people_idx
  39. else:
  40. test_face[i*( 170-k) + (j-k), :] = faceVector_im
  41. test_label[i*( 170-k) + (j-k)] = people_idx
  42. return train_face, train_label, test_face, test_label
  43. def PCA_fit( data, r):
  44. data = np.float32(np.mat(data))
  45. rows, cols = np.shape(data)
  46. data_mean = np.mean(data, 0)
  47. A = data - np.tile(data_mean, (rows, 1))
  48. C = A * A.T
  49. D, V = np.linalg.eig(C)
  50. V_r = V[:, 0:r]
  51. V_r = A.T * V_r
  52. for i in range(r):
  53. V_r[:, i] = V_r[:, i] / np.linalg.norm(V_r[:, i])
  54. final_data = A * V_r
  55. return final_data, data_mean, V_r
  56. if __name__ == "__main__":
  57. for r in [ 2, 3]:
  58. print( 'dimensionality of face images to {}:'. format(r))
  59. x_value = []
  60. y_value = []
  61. k = int( 170* 0.9)
  62. train_face, train_label, test_face, test_label = load_dataset(k)
  63. data_train_new, data_mean, V_r = PCA_fit(train_face[:- 501], r)
  64. data_train_new = np.array(data_train_new).astype( float)
  65. if r == 2:
  66. x_plot, y_plot = [], []
  67. for data in data_train_new:
  68. x_plot.append(data[ 0])
  69. y_plot.append(data[ 1])
  70. fig = plt.figure()
  71. plt.scatter(x_plot, y_plot)
  72. plt.show()
  73. if r == 3 :
  74. x_plot, y_plot, z_plot = [], [], []
  75. for data in data_train_new:
  76. x_plot.append(data[ 0])
  77. y_plot.append(data[ 1])
  78. z_plot.append(data[ 2])
  79. fig = plt.figure()
  80. ax = fig.add_subplot( 111,projection= '3d')
  81. plt.set_cmap(plt.get_cmap( "seismic", 100))
  82. im = ax.scatter(x_plot, y_plot, z_plot)
  83. ax.set_xlabel( 'x')
  84. ax.set_ylabel( 'y')
  85. ax.set_zlabel( 'z')
  86. plt.show()

PCA plus nearest neighbor classifification results


  
  1. import os
  2. from numpy import *
  3. import numpy as np
  4. import cv2
  5. import matplotlib.pyplot as plt
  6. from pylab import mpl
  7. def img2vector( im_path):
  8. im = cv2.imread(im_path, 0)
  9. rows, cols = im.shape
  10. imgVector = np.zeros(( 1, rows * cols))
  11. imgVector = np.reshape(im, ( 1, rows * cols))
  12. return imgVector
  13. def load_dataset( k):
  14. faceData_path = '../PIE'
  15. faceData_length = len(os.listdir(faceData_path))
  16. train_face = np.zeros((faceData_length * k, 32 * 32))
  17. train_label = np.zeros(faceData_length * k)
  18. test_face = np.zeros((faceData_length * ( 170 - k), 32 * 32))
  19. test_label = np.zeros(faceData_length * ( 170 - k))
  20. sample = random.permutation( 170) + 1
  21. for i in range(faceData_length):
  22. people_idx = i + 1
  23. if people_idx == 26:
  24. for j in range( 10):
  25. face_im_path = os.path.join(faceData_path, str(people_idx), str(j+ 1) + '.jpg')
  26. faceVector_im = img2vector(face_im_path)
  27. if j <= 7:
  28. train_face[i*k+j, :] = faceVector_im
  29. train_label[i*k + j] = people_idx
  30. else:
  31. test_face[i*( 170-k) + (j-k), :] = faceVector_im
  32. test_label[i*( 170-k) + (j-k)] = people_idx
  33. for j in range( 170):
  34. face_im_path = os.path.join(faceData_path, str(people_idx), str(sample[j]) + '.jpg')
  35. faceVector_im = img2vector(face_im_path)
  36. if j < k:
  37. train_face[i*k+j, :] = faceVector_im
  38. train_label[i*k + j] = people_idx
  39. else:
  40. test_face[i*( 170-k) + (j-k), :] = faceVector_im
  41. test_label[i*( 170-k) + (j-k)] = people_idx
  42. return train_face, train_label, test_face, test_label
  43. def PCA_fit( data, r):
  44. data = np.float32(np.mat(data))
  45. rows, cols = np.shape(data)
  46. data_mean = np.mean(data, 0)
  47. A = data - np.tile(data_mean, (rows, 1))
  48. C = A * A.T
  49. D, V = np.linalg.eig(C)
  50. V_r = V[:, 0:r]
  51. V_r = A.T * V_r
  52. for i in range(r):
  53. V_r[:, i] = V_r[:, i] / np.linalg.norm(V_r[:, i])
  54. final_data = A * V_r
  55. return final_data, data_mean, V_r
  56. if __name__ == "__main__":
  57. for r in [ 40, 80, 200]:
  58. print( 'dimensionality of face images to {}:'. format(r))
  59. x_value = []
  60. y_value = []
  61. k = int( 170* 0.7)
  62. train_face, train_label, test_face, test_label = load_dataset(k)
  63. data_train_new, data_mean, V_r = PCA_fit(train_face, r)
  64. num_train = data_train_new.shape[ 0]
  65. num_test = test_face.shape[ 0]
  66. temp_face = test_face - np.tile(data_mean, (num_test, 1))
  67. data_test_new = temp_face * V_r
  68. data_test_new = np.array(data_test_new)
  69. data_train_new = np.array(data_train_new)
  70. # -
  71. is_true_count = 0
  72. for i in range(num_test):
  73. testFace = data_test_new[i, :]
  74. diffMat = data_train_new - np.tile(testFace, (num_train, 1))
  75. sqDiffMat = diffMat ** 2
  76. sqDistances = sqDiffMat. sum(axis= 1)
  77. sortedDistIndicies = sqDistances.argsort()
  78. indexMin = sortedDistIndicies[ 0]
  79. if train_label[indexMin] == test_label[i]:
  80. is_true_count += 1
  81. else:
  82. pass
  83. accuracy = float(is_true_count) / num_test
  84. x_value.append(k)
  85. y_value.append( round(accuracy, 2))
  86. print( 'The classify accuracy is: {:.2f}'. format(accuracy* 100))

结果

PCA based data distribution visualization

PCA plus nearest neighbor classifification results

用于特征提取和分类的LDA

任务

应用LDA将数据维度从2、3和9降低维度分别为2和3的采样数据(如PCA部分)(类似于PCA)。分别报告维度为2、3和9的数据的分类精度,基于最近邻分类器。报告CMU PIE测试的分类准确性图片和你自己的照片分开。

实现代码

        这题不同于PCA那题,因为需要降低维度刚好是可视化需要的2,3,所以一个代码回答了两个问题。


   
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. import cv2
  4. from numpy import *
  5. import os
  6. def img2vector( im_path):
  7. im = cv2.imread(im_path, 0)
  8. rows, cols = im.shape
  9. imgVector = np.zeros(( 1, rows * cols))
  10. imgVector = np.reshape(im, ( 1, rows * cols))
  11. return imgVector
  12. def load_dataset( k):
  13. faceData_path = '../PIE'
  14. faceData_length = len(os.listdir(faceData_path))
  15. train_face = np.zeros((faceData_length * k, 32 * 32))
  16. train_label = np.zeros(faceData_length * k)
  17. test_face = np.zeros((faceData_length * ( 170 - k), 32 * 32))
  18. test_label = np.zeros(faceData_length * ( 170 - k))
  19. sample = random.permutation( 170) + 1
  20. for i in range(faceData_length):
  21. people_idx = i + 1
  22. if people_idx == 26:
  23. for j in range( 10):
  24. face_im_path = os.path.join(faceData_path, str(people_idx), str(j+ 1) + '.jpg')
  25. faceVector_im = img2vector(face_im_path)
  26. if j <= 7:
  27. train_face[i*k+j, :] = faceVector_im
  28. train_label[i*k + j] = people_idx
  29. else:
  30. test_face[i*( 170-k) + (j-k), :] = faceVector_im
  31. test_label[i*( 170-k) + (j-k)] = people_idx
  32. for j in range( 170):
  33. face_im_path = os.path.join(faceData_path, str(people_idx), str(sample[j]) + '.jpg')
  34. faceVector_im = img2vector(face_im_path)
  35. if j < k:
  36. train_face[i*k+j, :] = faceVector_im
  37. train_label[i*k + j] = people_idx
  38. else:
  39. test_face[i*( 170-k) + (j-k), :] = faceVector_im
  40. test_label[i*( 170-k) + (j-k)] = people_idx
  41. return train_face, train_label, test_face, test_label
  42. def LDA( face,label,k):
  43. x, y = face.shape
  44. classes = np.unique(label)
  45. meanAll = face.mean(axis= 0)
  46. Sb = np.zeros((y, y),dtype = np.float32)
  47. Sw = np.zeros((y, y), dtype=np.float32)
  48. for i in classes:
  49. face_i = face[np.where(label == i)[ 0],:]
  50. mean_i = face_i.mean(axis = 0)
  51. n = face_i.shape[ 0]
  52. Sw = Sw + np.dot((face_i - mean_i).T,(face_i-mean_i))
  53. Sb = Sb + n*np.dot((mean_i - meanAll).T,(mean_i - meanAll))
  54. #print("Sw");print(Sw);print("end");print("Sb");print(Sb);print("end")
  55. tmp = np.ones(Sw.shape)/ 500
  56. Sw = tmp + Sw
  57. matrix = np.linalg.inv(Sw) @ Sb
  58. eigenvalue,eigenvector = np.linalg.eigh(matrix)
  59. #print("vec");print(eigenvector);print("end")
  60. index = np.argsort(eigenvalue) # 排序
  61. index = index[:-(k + 1):- 1]
  62. select = eigenvector[:, index]
  63. return select
  64. def recognize_lda():
  65. eachNum = int( 170* 0.7) # 每个人拿出eachNum张照片进行训练
  66. train_face, train_label, test_face, test_label = load_dataset(eachNum)
  67. for k in [ 2, 3, 9]:
  68. print( 'when k={}:'. format(k), end= ' ')
  69. W = LDA(train_face, train_label, k)
  70. train = np.dot(train_face, W)
  71. test = np.dot(test_face, W)
  72. if k == 2:
  73. x_plot, y_plot = [], []
  74. for data in train[:- 501]:
  75. x_plot.append(data[ 0])
  76. y_plot.append(data[ 1])
  77. fig = plt.figure()
  78. plt.scatter(x_plot, y_plot)
  79. plt.show()
  80. if k == 3 :
  81. x_plot, y_plot, z_plot = [], [], []
  82. for data in train[:- 501]:
  83. x_plot.append(data[ 0])
  84. y_plot.append(data[ 1])
  85. z_plot.append(data[ 2])
  86. fig = plt.figure()
  87. ax = fig.add_subplot( 111,projection= '3d')
  88. plt.set_cmap(plt.get_cmap( "seismic", 100))
  89. im = ax.scatter(x_plot, y_plot, z_plot)
  90. ax.set_xlabel( 'x')
  91. ax.set_ylabel( 'y')
  92. ax.set_zlabel( 'z')
  93. plt.show()
  94. acc = KNN(train,train_label,test,test_label,eachNum)
  95. print( "the acc=", acc* 100);
  96. def KNN_classify( face,train_face,train_label,k):
  97. dis = np. sum(np.power((train_face - face), 2),axis= 1)
  98. index = np.argsort(dis)[:k]
  99. weight = []
  100. for i in range(k):
  101. weight.append(dis[index[k- 1]] - dis[index[i]] / (dis[index[k- 1]] - dis[index[ 0]]))
  102. count = [ 0 for i in range (train_face.shape[ 0])]
  103. tmp = 0
  104. for i in index:
  105. count[ int(train_label[i])] += 1 + weight[tmp]
  106. tmp += 1
  107. label = np.argmax(count);
  108. return label
  109. def KNN( train_faces, train_labels,test_faces, test_labels, k):
  110. sum = test_faces.shape[ 0]
  111. err = 0
  112. for i in range( sum):
  113. count = KNN_classify(test_faces[i],train_faces,train_labels,k)
  114. if count != test_labels[i]:
  115. err += 1
  116. acc = ( sum - err) / sum
  117. return acc
  118. if __name__ == "__main__":
  119. recognize_lda()

结果

LDA based data distribution visualization

LDA plus nearest neighbor classifification results


用于分类的SVM

任务

        使用原始面部图像(矢量化)和PCA预处理后的面部向量(维度为80和200)作为线性SVM的输入。惩罚参数C的尝试值{1×10英寸−2, 1 × 10−1, 1}. 报告不同参数和尺寸。讨论数据维度和参数C对最终分类的影响精确。

实现代码


   
  1. import os
  2. from numpy import *
  3. import numpy as np
  4. import cv2
  5. import matplotlib.pyplot as plt
  6. from pylab import mpl
  7. def img2vector( im_path):
  8. im = cv2.imread(im_path, 0)
  9. rows, cols = im.shape
  10. imgVector = np.zeros(( 1, rows * cols))
  11. imgVector = np.reshape(im, ( 1, rows * cols))
  12. return imgVector
  13. def load_dataset( k):
  14. faceData_path = '../PIE'
  15. faceData_length = len(os.listdir(faceData_path))
  16. train_face = np.zeros((faceData_length * k, 32 * 32))
  17. train_label = np.zeros(faceData_length * k)
  18. test_face = np.zeros((faceData_length * ( 170 - k), 32 * 32))
  19. test_label = np.zeros(faceData_length * ( 170 - k))
  20. sample = random.permutation( 170) + 1
  21. for i in range(faceData_length):
  22. people_idx = i + 1
  23. if people_idx == 26:
  24. for j in range( 10):
  25. face_im_path = os.path.join(faceData_path, str(people_idx), str(j+ 1) + '.jpg')
  26. faceVector_im = img2vector(face_im_path)
  27. if j <= 7:
  28. train_face[i*k+j, :] = faceVector_im
  29. train_label[i*k + j] = people_idx
  30. else:
  31. test_face[i*( 170-k) + (j-k), :] = faceVector_im
  32. test_label[i*( 170-k) + (j-k)] = people_idx
  33. for j in range( 170):
  34. face_im_path = os.path.join(faceData_path, str(people_idx), str(sample[j]) + '.jpg')
  35. faceVector_im = img2vector(face_im_path)
  36. if j < k:
  37. train_face[i*k+j, :] = faceVector_im
  38. train_label[i*k + j] = people_idx
  39. else:
  40. test_face[i*( 170-k) + (j-k), :] = faceVector_im
  41. test_label[i*( 170-k) + (j-k)] = people_idx
  42. return train_face, train_label, test_face, test_label
  43. def PCA_fit( data, r):
  44. data = np.float32(np.mat(data))
  45. rows, cols = np.shape(data)
  46. data_mean = np.mean(data, 0)
  47. A = data - np.tile(data_mean, (rows, 1))
  48. C = A * A.T
  49. D, V = np.linalg.eig(C)
  50. V_r = V[:, 0:r]
  51. V_r = A.T * V_r
  52. for i in range(r):
  53. V_r[:, i] = V_r[:, i] / np.linalg.norm(V_r[:, i])
  54. final_data = A * V_r
  55. return final_data, data_mean, V_r
  56. if __name__ == "__main__":
  57. for r in [ 80, 200]:
  58. for c in [ 0.01, 0.1, 1]:
  59. print( 'dimensionality of face images to {}, the value of parameter C is: {}'. format(r, c))
  60. x_value = []
  61. y_value = []
  62. k = int( 170* 0.7)
  63. train_face, train_label, test_face, test_label = load_dataset(k)
  64. data_train_new, data_mean, V_r = PCA_fit(train_face, r)
  65. data_train_new = np.array(data_train_new).astype( float)
  66. from sklearn import svm
  67. lin = svm.SVC(kernel= 'linear', C=c)
  68. lin.fit(data_train_new, train_label)
  69. predict = lin.predict(data_train_new)
  70. acc = sum(train_label==predict) // data_train_new.shape[ 0]
  71. print( 'accuarcy:{}'. format(acc* 100))

结果

用于分类的神经网络

任务

        训练具有两个卷积层和一个完全连接层的CNN,其架构如下:number节点数:20-50-500-21。最后一层的节点数固定为21执行21个类别(20个CMU PIE人脸加1个自己)分类。卷积内核大小设置为5。每个卷积层后面是一个最大池层内核大小为2,步幅为2。完全连接层之后是ReLU。训练网络并报告最终分类性能。

 实现代码


  
  1. import tensorflow as tf
  2. import os
  3. from numpy import *
  4. import numpy as np
  5. import cv2
  6. def load_dataset( k):
  7. faceData_path = '../PIE'
  8. faceData_length = len(os.listdir(faceData_path))
  9. train_face, train_label = [], []
  10. test_face, test_label = [], []
  11. sample = random.permutation( 170) + 1
  12. # 48, 68
  13. for i in range(faceData_length- 20, faceData_length):
  14. people_idx = i + 1
  15. for j in range( 170):
  16. face_im_path = os.path.join(faceData_path, str(people_idx), str(sample[j]) + '.jpg')
  17. faceVector_im = cv2.imread(face_im_path)
  18. if j < k:
  19. train_face.append(faceVector_im)
  20. train_label.append(people_idx-(faceData_length- 20))
  21. else:
  22. test_face.append(faceVector_im)
  23. test_label.append(people_idx-(faceData_length- 20))
  24. return np.array(train_face).astype( float), np.array(train_label), np.array(test_face).astype( float), np.array(test_label)
  25. if __name__ == '__main__':
  26. train_face, train_label, test_face, test_label = load_dataset( int( 170* 0.7))
  27. model = tf.keras.models.Sequential([
  28. tf.keras.layers.Conv2D(filters= 20,kernel_size=( 5, 5),padding= 'same',input_shape=( 32, 32, 3),activation= 'relu'),
  29. tf.keras.layers.MaxPool2D(pool_size=( 2, 2), strides= 2),
  30. tf.keras.layers.Conv2D(filters= 50,kernel_size=( 5, 5),padding= 'same',activation= 'relu'),
  31. tf.keras.layers.MaxPool2D(pool_size=( 2, 2), strides= 2),
  32. tf.keras.layers.Flatten(),
  33. tf.keras.layers.Dense( 500, activation= 'relu'),
  34. tf.keras.layers.Dense( 21,activation= 'softmax')])
  35. model. compile(optimizer= 'adam',loss= 'sparse_categorical_crossentropy',metrics=[ 'accuracy'])
  36. model.fit(train_face, train_label, epochs= 5) #训练模型
  37. model.evaluate(test_face, test_label, batch_size= 32,verbose= 2)

结果


转载:https://blog.csdn.net/qq_51831335/article/details/127587495
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场