SVM To Face Recognize

来源:互联网 发布:sql的distinct怎么删除 编辑:程序博客网 时间:2024/06/01 23:49

本文使用SVM进行人脸识别,并分析了选取不同的核函数(Kernel)以及penalty coefficient(C)对识别准确率的影响。

最后选择合适的核函数(Kernel)以及C使我们的识别率达到一个较高的水平。本文的代码实现基Python3.6 sklearn库。本文所用到的两个标准人脸库:ORL+Yale2

1、特征降维

ORL库每幅图片的大小是112*92,当用SVM进行人脸识别的时候,我们一般选择的处理方式是将图片展平(flatten)成一维数组,即112*92=10304。也即我们将每个图片当做一个实例,假设我们有400张图片,那么我们的训练集的大小将会是一个400*10304的一个二维矩阵,可以看出我们的特征维度有1W多维,虽然SVM可以处理这么高的特征维度,但是训练的时间代价就比较高,现在只是400幅图片,如果是上万张图片,训练时间可能会很久。

由于图片本身的像素之间存在着冗余性,局部邻域像素间存在的相似性,用PCA进行降维分析是一个不错的选择。但是我们需要降维到多少个特征呢?这个一般需要我们实验测试一下,对于每一个特定的kernel,都从[10 20 30 40 50]

分别测试降到不同维度时SVM表现的性能。结果如下图所示:







这里选择Components = 30,那么我们的数据集降维之后的大小就是400*30,极大的减少了数据量。

2、降维效果

那么降维之后效果如何呢?我们选择的30维的特征能否表示一幅人脸的主要特征呢?我们看看降维后的数据集中随机抽取40个实例,通过reshape回原图像尺寸,得到的Eigen Face(特征脸)

可以看到特征脸比较模糊,但是图像的大概轮廓是有了。当components增大后,得到的特征脸肯定是越来越清晰,但是准确率不一定会提高。因为参数越多,越可能会出现过拟合。

3、分析选择合适的核函数

我们通过选择了sklearn.SVM库中的四个核函数,linear, poly, rbf, sigmoid。通过交叉验证分析它们的准确性,选择一个表现最高的核作为我们最后的识别。


可以看到线性核函数表现性能最好,且线性核函数处理更快

4、确定惩罚系数C对不同的核函数的影响(注意结果都是在默认配置下的SVM上得到的)


可以看到C=10以后再增大,结果基本不变

5、训练+测试

通过以上实验分析,最终确定kernel='linear', C=10, Components=30。随机抽取40张预测结果如下图显示


在ORL库上的Accuracy为:97%


6、同样的步骤在Yale2人脸库上进行,Components=30。Eigen Face如图所示:


7、kernel='linear', C=10,Components=30,预测结果如图所示:


在Yale2上的准确率为92.8%:

8、注意事项

在使用RBF核的时候,特征要归一化处理。一般来说,使用任何一个分类器,都可以先将特征进行归一化处理,有时候可以加快收敛速度(例如梯度下降算法),有些时候将严重影响算法的性能(RBG 等)。

# !/usr/bin/env python# -*- coding:utf-8 -*- # Author: wsw# 用SVC实现人脸识别from sklearn.svm import SVCfrom sklearn.model_selection import train_test_splitfrom sklearn.model_selection import cross_val_score, ShuffleSplitfrom sklearn.decomposition import PCAfrom sklearn.preprocessing import StandardScalerimport numpy as npimport osimport reimport matplotlib.pyplot as pltimport randompath = r'E:\pythonfile_withpycharm\SVMLearning\faceLibrary\人脸库\ORL'path2 = r'E:\pythonfile_withpycharm\SVMLearning\faceLibrary\人脸库\Yale2'# 将piclist中后缀名字为.bmp图片的名字选取出来def getPicList(filepath):filelist = os.listdir(filepath)piclist = []for pic in filelist:# os.path.splitext()用于分离文件名字和扩展名if os.path.splitext(pic)[1] == '.bmp':piclist.append(pic)return piclistpass# 得到人脸数据def getFaceData(picPath, piclist):faceData = []labels = []count = 1for picname in piclist:p = plt.imread(picPath + '\\' + picname)# 得到每幅人脸数据的大小if count:m, n = p.shapecount -= 1# 将一个图片数据展成一行data = p.ravel()faceData.append(data)# 搜索每个图片的类别,以下划线为结束符pattern = re.compile('(\d+)_')res = re.findall(pattern, picname)# 将字符串转换为数字label = int(res[0])labels.append(label)faceData = np.array(faceData)labels = np.array(labels)return faceData, labels, m, npass# 对faceData数据降维def dimensionReduce(faceData, labels, ncomponents):pca = PCA(n_components=ncomponents)reduceddata = pca.fit_transform(faceData, labels)# print('降维后特征的方差占比:')# print(pca.explained_variance_ratio_)return reduceddata, pcapass# 用svc进行训练def callSVC(data, labels, kernel, C=1):# 切分数据集xtrain, xtest, ytrain, ytest = train_test_split(data, labels, test_size=0.25, random_state=33)# print(xtrain.shape, xtest.shape)# 寻找测试集在数据集中的行索引rowindex = []for i, x in enumerate(xtest):index = np.where(data == x)rowindex.append([index[0][0], i])# 将训练数据经行归一化处理ss = StandardScaler()xtrain = ss.fit_transform(xtrain)xtest = ss.transform(xtest)# 定义svcsvc = SVC(kernel=kernel, C=C)# 进行10折交叉验证cv = ShuffleSplit(n_splits=10, test_size=0.25, random_state=33)scores = cross_val_score(svc, xtrain, ytrain, cv=cv, verbose=0)print('验证集平均准确率:', np.mean(scores))svc.fit(xtrain, ytrain)print('训练集拟合程度:', svc.score(xtrain, ytrain))predict = svc.predict(xtest)print('测试集准确率:', svc.score(xtest, ytest))return rowindex, ytest, predictpass# 可视化的显示部分人脸识别结果def showFaceRecognization(facesubset, labelsubset, predictsubset, m, n):plt.figure(figsize=(10, 6))for i, facedata in enumerate(facesubset):plt.subplot(4, 10, i + 1)face = np.array(facedata).reshape(m, n)plt.imshow(face)plt.xticks([])plt.yticks([])plt.title('class%d' % labelsubset[i])plt.xlabel('predict%d' % predictsubset[i])# plt.show()pass# 显示经过PCA降维之后的特征脸def showEigFace(reduceddata, pca, m, n):plt.figure(figsize=(10, 6))plt.title('Eig Face')# 随机选取40个特征脸经行显示nums = reduceddata.shape[0]indexes = random.sample(range(nums), 40)for i, index in enumerate(indexes):plt.subplot(4, 10, i + 1)plt.xticks([])plt.yticks([])eigface = pca.inverse_transform(reduceddata[index, :])eigface = eigface.reshape(m, n)plt.imshow(eigface)# plt.show()pass# PCA降维性能分析def pcaAnalysis(estimator, facedata, labels, kernel):ncomponents = [10, 20, 30, 40, 50]Accuracy = []for ncomponent in ncomponents:pca = PCA(n_components=ncomponent)reduceddata = pca.fit_transform(facedata, labels)xtrain, xtest, ytrain, ytest = train_test_split(reduceddata, labels, test_size=0.25, random_state=3)# 数据归一化处理ss = StandardScaler()xtrain = ss.fit_transform(xtrain)xtest = ss.transform(xtest)estimator.fit(xtrain, ytrain)Accuracy.append(estimator.score(xtest, ytest))plt.figure(figsize=(8, 6))plt.title('%s Kernel Accuracy With Different Components' % kernel)plt.bar(ncomponents, Accuracy, color=['r', 'g', 'b', 'm', 'c'])plt.xlabel('components')plt.yticks(np.linspace(0, 1, 20))# 给图形添加真实标注for a, b in zip(ncomponents, Accuracy):plt.text(a, b + 0.01, '%f' % b, ha='center', va='bottom', fontsize=7)pass# 得到PCA分析结果def getPCAResult(facedata, labels):kernels = ['linear', 'rbf', 'sigmoid', 'poly']for kernel in kernels:svc = SVC(kernel=kernel)pcaAnalysis(svc, facedata, labels, kernel)pass# 不同的核函数性能分析def getAccuracyWithKernel(reduceddata, labels):kernels = ['linear', 'sigmoid', 'rbf', 'poly']ss = StandardScaler()xtrain, xtest, ytrain, ytest = train_test_split(reduceddata, labels, test_size=0.25, random_state=3)xtrain = ss.fit_transform(xtrain)xtest = ss.transform(xtest)val_scores = []test_scores = []# 10折交叉验证for kernel in kernels:svc = SVC(kernel=kernel)seed = random.randint(0, 40)cv = ShuffleSplit(n_splits=10, test_size=0.1, random_state=seed)val_scores.append(np.mean(cross_val_score(svc, xtrain, ytrain, cv=cv)))svc.fit(xtrain, ytrain)test_scores.append(svc.score(xtest, ytest))plt.figure(figsize=(8, 6))plt.bar(range(1, 5), val_scores, width=0.2, color='c', label='validation')plt.bar(np.arange(1, 5) + 0.2, test_scores, width=0.2, color='m', label='test')plt.legend(loc='best')plt.yticks(np.linspace(0, 1, 20))plt.xticks([])# 标注数据x = np.arange(1, 5) + 0.2for a, b, kernel in zip(x, test_scores, kernels):plt.text(a, b + 0.01, '%.3f' % b, ha='center', va='bottom', fontsize=7)plt.text(a, -0.05, kernel, ha='center', va='bottom', fontsize=12)for a, b in zip(range(1, 5), val_scores):plt.text(a, b + 0.01, '%.3f' % b, ha='center', va='bottom', fontsize=7)pass# 测试惩罚参数C的影响def getAccuracyWithC(reduceddata, labels):clist = [0.001, 0.01, 0.1, 1, 10, 100]kernels = ['linear', 'sigmoid', 'rbf', 'poly']ss = StandardScaler()xtrain, xtest, ytrain, ytest = train_test_split(reduceddata, labels, test_size=0.25, random_state=3)xtrain = ss.fit_transform(xtrain)xtest = ss.transform(xtest)plt.figure(figsize=(8, 6))color = ['r', 'g', 'b', 'y']for i, kernel in enumerate(kernels):test_scores = []for c in clist:svc = SVC(kernel=kernel, C=c)svc.fit(xtrain, ytrain)test_scores.append(svc.score(xtest, ytest))plt.semilogx(clist, test_scores, '-p', c=color[i], label='%s' % kernel)plt.legend(loc='best')plt.yticks(np.linspace(0, 1, 20))plt.title('Accuracy with different value of C')plt.xlabel('Value Of C')passdef main(filepath):piclists = getPicList(filepath)facedata, labels, m, n = getFaceData(filepath, piclists)# 得到PCA分析结果getPCAResult(facedata, labels)reducedData, pca = dimensionReduce(facedata, labels, 30)# 得到不同核函数的效果getAccuracyWithKernel(reducedData, labels)# 得到不同C的效果getAccuracyWithC(reducedData, labels)rowindex, ytest, predict = callSVC(reducedData, labels, kernel='linear', C=1)# 随机抽取40个人脸进行显示index = random.sample(rowindex, 40)index = np.array(index)facesubset = facedata[index[:, 0], :]labelsubset = labels[index[:, 0]]predictsubset = predict[index[:, 1]]# 可视化预测结果showFaceRecognization(facesubset, labelsubset, predictsubset, m, n)# 可视化降维后特征脸showEigFace(reducedData, pca, m, n)plt.show()main(path2)



原创粉丝点击