[350]Scikit 您所在的位置:网站首页 orl人脸数据库下载 [350]Scikit

[350]Scikit

2023-08-11 15:26| 来源: 网络整理| 查看: 265

理论基础

本算法流程就是用主成分分析(Pca)对人脸数据集进行降维,得到数个人脸特征向量。对于任意一个人脸样本,将样本数据向特征向量投影,得到的投影系数作为人脸的特征表示。使用支持向量机(SVM)对这些不同的投影系数向量分类,来进行人脸识别。

(1)人脸识别经典算法:特征脸(Eigenface)人脸识别之特征脸

(2)主成分分析:主成分分析PCA

(3)支持向量机:支持向量机SVM

实例分析

Scikit实例使用的是Labeled Faces in the Wild(LFW)数据集,大约有220M,为了避免下载麻烦或者处理数据较慢,本例使用了英国剑桥大学的AT&T人脸数据:AT&T数据集下载. 该数据集大小不到5M,有40类样本,每类中包含同一个人的10张图像(112*92)。

首先是读入数据集,将每一幅图像拉成一列,组成数据集合(112*92,400),并保存每一列数据对应的人脸标号,以及原图的高度和宽度,为了处理后还原显示。下面为数据读入代码,读入图像使用了opencv的imread函数,并将数据转换了为numpy的array便于后续操作。

PICTURE_PATH = "D:\\Data\\" def get_Image(): for i in range(1,41): for j in range(1,11): path = PICTURE_PATH + "\\s" + str(i) + "\\"+ str(j) + ".pgm" img = cv2.imread(path) img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) h,w = img_gray.shape img_col = img_gray.reshape(h*w) all_data_set.append(img_col) all_data_label.append(i) return h,w all_data_set = [] all_data_label = [] h,w = get_Image() X = array(all_data_set) y = array(all_data_label) n_samples,n_features = X.shape n_classes = len(unique(y)) target_names = [] for i in range(1,41): names = "person" + str(i) target_names.append(names) print("Total dataset size:") print("n_samples: %d" % n_samples) print("n_features: %d" % n_features) print("n_classes: %d" % n_classes)

image.png 然后进行数据集的划分,一部分用于训练集,另一部分用于测试集。本例使用四分之三的数据用于训练,四分之一数据用于测试。

random_state:随机数种子——其实就是该组随机数的编号,在需要重复试验的时候,保证得到一组一样的随机数。比如每次都为1,其他参数一样的情况下你得到的随机数组是一样的。当为None时,产生的随机数组也会是随机的。

随机数的产生取决于种子,随机数和种子之间的关系遵从以下两个规则:种子不同,产生不同的随机数;种子相同,即使实例不同也产生相同的随机数。

random_state 设置相同,那么当别人重新运行你的代码的时候就能得到完全一样的结果,复现和你一样的过程。如果你设置为 None,则会随机选择一个种子。

#split into a training and testing set X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.25, random_state=42)

下面是主成分分析的部分,重点是选取保留主成分的个数,不同个数特征向量的检测性能不同,本文最后会给出一些测试结果。暂时先取前20个。

n_components = 20 print("Extracting the top %d eigenfaces from %d faces" % (n_components, X_train.shape[0])) t0 = time() pca = PCA(n_components=n_components, svd_solver='randomized', #选择一种svd方式 whiten=True).fit(X_train) #whiten是一种数据预处理方式,会损失一些数据信息,但可获得更好的预测结果 print("done in %0.3fs" % (time() - t0)) eigenfaces = pca.components_.reshape((n_components, h, w)) #特征脸 print("Projecting the input data on the eigenfaces orthonormal basis") t0 = time() X_train_pca = pca.transform(X_train) #得到训练集投影系数 X_test_pca = pca.transform(X_test) #得到测试集投影系数 print("done in %0.3fs" % (time() - t0))

image.png 这前20个特征向量就是特征脸,可以显示一些出来看看:

def plot_gallery(images, titles, h, w, n_row=3, n_col=4): """Helper function to plot a gallery of portraits""" plt.figure(figsize=(1.8 * n_col, 2.4 * n_row)) plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35) for i in range(n_row * n_col): plt.subplot(n_row, n_col, i + 1) plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray) plt.title(titles[i], size=12) plt.xticks(()) plt.yticks(()) eigenface_titles = ["eigenface %d" % i for i in range(eigenfaces.shape[0])] plot_gallery(eigenfaces, eigenface_titles, h, w) plt.show()

image.png 在上一步,得到了特征脸,并且得到了训练集和测试集在特征向量的投影系数,下面就是利用训练集的(投影系数+标号)训练出一个SVM分类器,用于测试集的识别啦。本例SVM使用的是最常用的高斯核(也称RBF),如果你熟悉SVM方程的话,应该知道SVM需要确定的两个重要参数C和gama,其中C为惩罚因子,越大模型对训练数据拟合程度越高,gama是高斯核参数。一般采用网格搜索的方式及C和gama各给一系列值,分别训练模型,选择最优的C和gama。例如C : 2.-5,2.-3,…,2.^15 , gama:2.-15,2.-13,…,2.^3(随便举得例子)。此外,由于防止对训练数据过拟合,一般寻找最优参数的模型检验方式是交叉检验(cross-validation),即初始化多组训练数据和测试数据取平均结果,GridSearchCV函数正是如此。

print("Fitting the classifier to the training set") t0 = time() param_grid = {'C': [1e3, 5e3, 1e4, 5e4, 1e5], 'gamma': [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1], } clf = GridSearchCV(SVC(kernel='rbf', class_weight='balanced'), param_grid) #class_weight='balanced'表示调整各类别权重,权重与该类中样本数成反比, #防止模型过于拟合某个样本数量过大的类 clf = clf.fit(X_train_pca, y_train) print("done in %0.3fs" % (time() - t0)) print("Best estimator found by grid search:") print(clf.best_estimator_)

image.png 核心部分已经完成了,最后就是用训练好的SVM分类器去做识别了。

print("Predicting people's names on the test set") t0 = time() y_pred = clf.predict(X_test_pca) print("done in %0.3fs" % (time() - t0)) print(classification_report(y_test, y_pred, target_names=target_names)) print(confusion_matrix(y_test, y_pred, labels=range(n_classes)))

image.png

image.png 左图输出结果的表头,右图为输出结果的表尾,几项指标含义分别为(查准率/查全率/F1值/测试样本数),有关这几项含义可以看看:评价指标。另外就是不知道为什么只有39类,可是划分数据时是有第40的,调试了好一会儿,也没找到错在哪了。

再可视化一下测试结果:

# plot the result of the prediction on a portion of the test set def title(y_pred, y_test, target_names, i): pred_name = target_names[y_pred[i]-1] true_name = target_names[y_test[i]-1] return 'predicted: %s\ntrue: %s' % (pred_name, true_name) prediction_titles = [title(y_pred, y_test, target_names, i) for i in range(y_pred.shape[0])] plot_gallery(X_test, prediction_titles, h, w)

image.png 最后再说一下主成分数对识别结果性能的影响:

image.png 这是n=10的测试结果,比n=20更好。 image.png 这是n=5的测试结果,比n=20更差。

这两组测试说明,选择主成分数不能过大也不能过小,太多则表示的过于具体,太小则表示的过于笼统,检测效果均不佳,实际使用时要根据实验结果找到最好的主成分数。

以上分代码没写载入库文件,完整代码:

# -*- coding:utf-8 -*- from __future__ import print_function from time import time import logging,cv2 import matplotlib.pyplot as plt from numpy import * from sklearn.model_selection import train_test_split,GridSearchCV from sklearn.metrics import classification_report,confusion_matrix from sklearn.decomposition import PCA from sklearn.svm import SVC PICTURE_PATH = "./att_faces" def get_Image(): for i in range(1, 41): for j in range(1, 11): path = PICTURE_PATH + "\\s" + str(i) + "\\" + str(j) + ".pgm" img = cv2.imread(path) img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) h, w = img_gray.shape img_col = img_gray.reshape(h * w) all_data_set.append(img_col) all_data_label.append(i) return h, w all_data_set = [] all_data_label = [] h, w = get_Image() X = array(all_data_set) y = array(all_data_label) n_samples, n_features = X.shape n_classes = len(unique(y)) #numpy.unique() target_names = [] for i in range(1, 41): names = "person" + str(i) target_names.append(names) print("Total dataset size:") print("n_samples: %d" % n_samples)#400 print("n_features: %d" % n_features)#10304 print("n_classes: %d" % n_classes)#40 # split into a training and testing set ''' random_state:随机数种子——其实就是该组随机数的编号,在需要重复试验的时候,保证得到一组一样的 随机数。比如每次都为1,其他参数一样的情况下你得到的随机数组是一样的。当为None时,产生的随机数组 也会是随机的。 随机数的产生取决于种子,随机数和种子之间的关系遵从以下两个规则:种子不同,产生不同的随机数; 种子相同,即使实例不同也产生相同的随机数。 ''' X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42) n_components = 10 print("Extracting the top %d eigenfaces from %d faces"% (n_components, X_train.shape[0])) t0 = time() #选择一种svd方式,whiten是一种数据预处理方式,会损失一些数据信息,但可获得更好的预测结果 pca = PCA(n_components=n_components, svd_solver='randomized',whiten=True).fit(X_train) print("done in %0.3fs" % (time() - t0)) eigenfaces = pca.components_.reshape((n_components, h, w))#特征脸 print("Projecting the input data on the eigenfaces orthonormal basis") t0 = time() X_train_pca = pca.transform(X_train)#得到训练集投影系数 X_test_pca = pca.transform(X_test)#得到测试集投影系数 print("done in %0.3fs" % (time() - t0)) print("Fitting the classifier to the training set") t0 = time() '''C为惩罚因子,越大模型对训练数据拟合程度越高,gama是高斯核参数''' param_grid = {'C': [1e3, 5e3, 1e4, 5e4, 1e5], 'gamma': [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1], } ''' class_weight='balanced' 表示调整各类别权重,权重与该类中样本数成反比,防止模型过于拟合某个样本数量过大的类 ''' clf = GridSearchCV(SVC(kernel='rbf', class_weight='balanced'), param_grid) clf = clf.fit(X_train_pca, y_train) print("done in %0.3fs" % (time() - t0)) print("Best estimator found by grid search:") print(clf.best_estimator_) print("Predicting people's names on the test set") t0 = time() y_pred = clf.predict(X_test_pca) print("done in %0.3fs" % (time() - t0)) print(classification_report(y_test, y_pred, target_names=target_names)) print(confusion_matrix(y_test, y_pred, labels=range(n_classes))) def plot_gallery(images, titles, h, w, n_row=3, n_col=3): """Helper function to plot a gallery of portraits""" plt.figure(figsize=(1.8 * n_col, 2.4 * n_row)) plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35) for i in range(n_row * n_col): plt.subplot(n_row, n_col, i + 1) #cmap: 颜色图谱(colormap), 默认绘制为RGB(A)颜色空间 plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray) plt.title(titles[i], size=12) plt.xticks(()) plt.yticks(()) # plot the result of the prediction on a portion of the test set def title(y_pred, y_test, target_names, i): pred_name = target_names[y_pred[i] - 1] true_name = target_names[y_test[i] - 1] return 'predicted: %s\ntrue: %s' % (pred_name, true_name) prediction_titles = [title(y_pred, y_test, target_names, i) for i in range(y_pred.shape[0])] plot_gallery(X_test, prediction_titles, h, w) # plot the gallery of the most significative eigenfaces eigenface_titles = ["eigenface %d" % i for i in range(eigenfaces.shape[0])] plot_gallery(eigenfaces, eigenface_titles, h, w) plt.show()

imshow()函数格式为:

matplotlib.pyplot.imshow(X, cmap=None)

X: 要绘制的图像或数组。

cmap: 颜色图谱(colormap), 默认绘制为RGB(A)颜色空间。 其它可选的颜色图谱如下列表:

颜色图谱描述autumn红-橙-黄bone黑-白,x线cool青-洋红copper黑-铜flag红-白-蓝-黑gray黑-白hot黑-红-黄-白hsvhsv颜色空间, 红-黄-绿-青-蓝-洋红-红inferno黑-红-黄jet蓝-青-黄-红magma黑-红-白pink黑-粉-白plasma绿-红-黄prism红-黄-绿-蓝-紫-…-绿模式spring洋红-黄summer绿-黄viridis蓝-绿-黄winter蓝-绿

来源 :https://blog.csdn.net/mingtian715/article/details/54380623 https://blog.csdn.net/vicdd/article/details/52647906



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有