SVM实现人脸识别(超详细易懂)(一)

机器学习的本质:从大量数据里提取出特征与相应的类别产生联系,该类别称之为标签,也就是说使得特征与对应的标签产生对应关系,从而具有识别的能力。
分类和聚类分类是已知物体的类别的标签,聚类则是数据处于无标签状态,我们把具有相似特征的物体归为同一类。分类是有监督的学习,有标签(预设标准答案);聚类是无监督的学习,无标签。
SVM实现人脸识别(超详细易懂)(一)
文章图片

SVM(Support Vector Machine)支持向量机:是机器学习里非常常见的算法,其本质是把两个不同类别的数据样本,通过找到一条理想中的最优超平面,(一个面是一条线,三维是一个面,如果是高维的则需要找到一个最优的超平面)使得后续的数据添加进来后仍然可以划分数据。理想中是找到两类数据中最中间的分界线,以上图为例,找到最接近的红点和蓝点,然后从他们中间找到最优的平面,这样的两个点称为支持向量。SVM实现人脸识别(超详细易懂)(一)
文章图片

但如果是这种情况则很难找到一条线对红点蓝点进行划分。则我们需要把这样的二维问题映射到高维的空间中。SVM实现人脸识别(超详细易懂)(一)
文章图片
比如可以想象:这里有一张桌子,红点和蓝点都可以从桌子上跳起来,蓝点比较沉,则跳的就很低,红点很轻,跳的比较高,通过这种方式,我们就可以很轻松的找到一条线,再次把红蓝点区分开来。遇到线性不可分的问题时,我们通常把这样的问题通过核函数映射到高维空间,只要维度够高,所有的问题都可以进行线性划分。SVM实现人脸识别(超详细易懂)(一)
文章图片

二维映射到三维的例子
SVM实现人脸识别(超详细易懂)(一)
文章图片

那么此时如果数据中再加入两个未知颜色的点,则位于线的上方我们就把其归于蓝色,位于线的下方则把其归于红色。
计算超平面的方法如下,其具体的数学分析我们会在下一章节描述。SVM实现人脸识别(超详细易懂)(一)
文章图片
SVM实现人脸识别(超详细易懂)(一)
文章图片
SVM实现人脸识别(超详细易懂)(一)
文章图片

大体思路是先根据支持向量找到两个超平面,然后寻找中间的目标超平面,根据拉格朗日的对偶问题求解超平面的参数值。具体推导过程下一章节中讲。

warnings.filterwarnings("ignore") PICTURE_PATH="C:\" 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=mpimg.imread(path) h,w=img.shape img_col=img.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)` 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 basics") 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()-10)) print("Best estimator found by grid search:") print(clf.best_estimator_) print("Predicting people's names on test set") t0=time() y_pred=clf.predict(X_test_pca) print("done in %0.3"%(time()-10)) 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): plt.figure(figsize=(1.8*n_col,2.4*n_row)) plt.subplot_adjust(bottom=0,left=.01,right=.99,top=.90,hspace=.35) for i in range(10): plt.subplot(n_row,n_col,i+1) plt.imshow(images[i].reshape((h,w)),cmap=plt.cm.gray) plt.title(title[i].size=12) plt.xticks(()) plt.yticks(()) 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] retuen '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)eigenface_titles=["eigenface %d" % i for i in range(eigenfaces,shape[0])] plot_gallery(eigenfaces,eigenface_titles,h,w) ply.show()

【SVM实现人脸识别(超详细易懂)(一)】代码如上
代码部分解析
y是图像的标签,添加图形数字矩阵和特征,并最图像进行一个数据统计:图像张数,特征,多少类
*X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.25,random_state=42)
*根据图像和对应标签划分为训练集和测试集,测试集所占的比重为25%
eigenfaces=pca.components_.reshape((n_components,h,w))
SVM实现人脸识别(超详细易懂)(一)
文章图片

对图像做主成分分析生成很多特征脸,我们可以认为每一张图像都是由特征脸叠加而成的,特征脸是根据图像进行主成分分析得到的,可以理解为每个人脸的一些特征,将这些特征叠加起来就可以得到一张清晰的人脸。通过主成分分析,我们可以抽取每一张图像的特征脸
*X_train_pca=pca.transform(X_train)
X_test_pca=pca.transform(X_test)

然后把图像根据特征脸做转化提取里面的特征。
param_grid={‘C’:[1e3,5e3,1e4,5e4,1e5],
‘gamma’:[0.0001,0.0005,0.001,0.005,0.01,0.1],}

设置SVM里的必要参数,C是惩罚系数,gamma是学习值,即允许的间隔值
clf=GridSearchCV(SVC(kernel=‘rbf’,class_weight=‘balanced’),param_grid)
通过网格搜索的方式,调整SVC(SVM分类器),C和gamam的组合有5
6=30个,那么我们现在希望找到一个最好的参数组合,使得SVM表示最好,所以网格搜索就是一个一个实验30个组合得到的参数运行程序,观察哪一种组合的表现是最好的,从而得到最优的超参数。
clf=clf.fit(X_train_pca,y_train)
得到最优超参数后训练我们的模型,将训练集得到的特征和与之对应的标签放进模型中训练,此时模型就可以找到一个对于这部分训练数据来说最优的超平面clf.best_estimator_。
找到之后我们用得到的最优超平面去预测测试集的特征
y_pred=clf.predict(X_test_pca)
每一个测试集的特征,与之对应的都会给出一个y_pred预测的结果。
print(classification_report(y_test,y_pred,target_names=target_names))
将预测的结果输出就会得到一个预测的准确率SVM实现人脸识别(超详细易懂)(一)
文章图片

预测结果和准确率表示
def plot_gallery(images,titles,h,w,n_row=3,n_col=4)

画图的函数,首先生成界面plt.subplot_adjust(bottom=0,left=.01,right=.99,top=.90,hspace=.35)
挨个展示图像和预测值(title为预测值)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)
展示预测值
eigenface_titles=[“eigenface %d” % i for i in range(eigenfaces,shape[0])]
展示了一部分特征脸
代码为纯手打,因此可能有很多bug,建议仔细调试后再使用

    推荐阅读