Scikit-learn实例之Pca+Svm人脸识别(AT&T数据集)
2017-01-12 20:36
405 查看
理论基础
本算法流程就是用主成分分析(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便于后续操作。
然后进行数据集的划分,一部分用于训练集,另一部分用于测试集。本例使用四分之三的数据用于训练,四分之一数据用于测试。
下面是主成分分析的部分,重点是选取保留主成分的个数,不同个数特征向量的检测性能不同,本文最后会给出一些测试结果。暂时先取前20个。
[align=left]这前20个特征向量就是特征脸,可以显示一些出来看看:
[/align]
在上一步,得到了特征脸,并且得到了训练集和测试集在特征向量的投影系数,下面就是利用训练集的(投影系数+标号)训练出一个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函数正是如此。
核心部分已经完成了,最后就是用训练好的SVM分类器去做识别了。
左图输出结果的表头,右图为输出结果的表尾,几项指标含义分别为(查准率/查全率/F1值/测试样本数),有关这几项含义可以看看:评价指标。另外就是不知道为什么只有39类,可是划分数据时是有第40的,调试了好一会儿,也没找到错在哪了。
再可视化一下测试结果:
最后再说一下主成分数对识别结果性能的影响:
这是n=10的测试结果,比n=20更好。
这是n=5的测试结果,比n=20更差。
这两组测试说明,选择主成分数不能过大也不能过小,太多则表示的过于具体,太小则表示的过于笼统,检测效果均不佳,实际使用时要根据实验结果找到最好的主成分数。
以上分代码没写载入库文件,完整代码:
如果这篇文章对你有帮助,可以点个赞或者关注我,我会更有动力分享学习过程,谢啦~
本算法流程就是用主成分分析(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)
然后进行数据集的划分,一部分用于训练集,另一部分用于测试集。本例使用四分之三的数据用于训练,四分之一数据用于测试。
#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))
[align=left]这前20个特征向量就是特征脸,可以显示一些出来看看:
[/align]
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()
在上一步,得到了特征脸,并且得到了训练集和测试集在特征向量的投影系数,下面就是利用训练集的(投影系数+标号)训练出一个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_)
核心部分已经完成了,最后就是用训练好的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)))
左图输出结果的表头,右图为输出结果的表尾,几项指标含义分别为(查准率/查全率/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)
最后再说一下主成分数对识别结果性能的影响:
这是n=10的测试结果,比n=20更好。
这是n=5的测试结果,比n=20更差。
这两组测试说明,选择主成分数不能过大也不能过小,太多则表示的过于具体,太小则表示的过于笼统,检测效果均不佳,实际使用时要根据实验结果找到最好的主成分数。
以上分代码没写载入库文件,完整代码:
from __future__ import print_function
from time import time
import logging
import matplotlib.pyplot as plt
import cv2
from numpy import *
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.decomposition import PCA
from sklearn.svm import SVC
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)
# 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)
n_components = 10
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',
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()
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)
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=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(())
# 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()
如果这篇文章对你有帮助,可以点个赞或者关注我,我会更有动力分享学习过程,谢啦~
相关文章推荐
- Python scikit-learn 学习笔记—PCA+SVM人脸识别
- 利用Python sklearn的SVM对AT&T人脸数据进行人脸识别
- 数据挖掘—LDA,PCA特征提取降维与SVM多分类在人脸识别中的应用-数据集ORL
- Matlab PCA+SVM人脸识别(一)
- 基于MATLAB,运用PCA+SVM的特征脸方法人脸识别
- 【Python学习系列二十三】Scikit_Learn库降维方法(矩阵分解)-PCA&FA
- [opencv][python][scikit-learn]att_faces数据人脸识别
- Matlab PCA+SVM人脸识别(二)——GUI界面设计
- 机器学习:scikit-learn 做笑脸识别 (SVM, KNN, Logisitc regression)
- 机器学习教程 之 SKlearn 中 PCA 算法的运用:人脸识别实例
- 基于PCA和SVM的人脸识别系统-error修改
- 基于MATLAB,运用PCA+SVM的特征脸方法人脸识别
- PCA+SVM人脸识别
- (11)MATLAB PCA+SVM 人脸识别
- PCA + SVM 人脸识别
- 基于PCA和SVM的人脸识别
- Matlab PCA+SVM人脸识别(一)
- 使用OpenCV+PCA+KNN/SVM进行人脸检测和识别-Python
- 基于PCA和SVM人脸识别之二.MATLAB实现
- Scikit-learn实例之理解SVM正则化系数C