【模式识别】SVM实现人脸表情分类

前言

本文是模式识别课程关于支持向量机(SVM)算法的课程设计,根据人脸的面部特征,通过SVM算法将表情分为7类。
本文的jupyter文件和数据集下载地址:
https://download.csdn.net/download/qq1198768105/66912662

数据集

本文采用的数据集为The Japanese Female Facial Expression (JAFFE) Dataset
数据集来源:https://zenodo.org/record/3451524#.YaeJztBByUl
共有七个类别:anger、disgust、fear、happiness、neutral、sadness、surprise

导库

import os
import numpy as np
import cv2
import matplotlib.pyplot as plt
import seaborn

from sklearn.svm import SVC
from skimage.feature import hog
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score

数据预处理

读入图像,转换成灰度,大小转换成256*256,数据归一化

def preprocessing(src):
    gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)  # 将图像转换成灰度图
    img = cv2.resize(gray, (256, 256))  # 尺寸调整g
    img = img/255.0    # 数据归一化
    return img

特征提取

采用Hog批量提取图片特征

采用方向梯度直方图(Histograms of Oriented Gradient,HOG)来提取特征,法国研究人员Dalal在2005的CVPR提出HOG+SVM的方法,优点是图像几何的和光学的形变都能保持很好的不变性。

关于HOG的原理和步骤流程可参考下面两篇文章。
https://blog.csdn.net/zouxy09/article/details/7929348
https://blog.csdn.net/qq_34106574/article/details/88317902

def extract_hog_features(X):
    image_descriptors = []
    for i in range(len(X)):
        '''
        参数解释:
        orientations:方向数
        pixels_per_cell:胞元大小
        cells_per_block:块大小
        block_norm:可选块归一化方法L2-Hys(L2范数)
        visualize:可视化
        '''
        fd, _ = hog(X[i], orientations=9, pixels_per_cell=(16, 16), cells_per_block=(16, 16), block_norm='L2-Hys', visualize=True)
        image_descriptors.append(fd)  # 拼接得到所有图像的hog特征
    return image_descriptors        # 返回的是训练部分所有图像的hog特征

提取单张图片特征

def extract_hog_features_single(X):
    image_descriptors_single = []
    fd, _ = hog(X, orientations=9, pixels_per_cell=(16, 16), cells_per_block=(16, 16),block_norm='L2-Hys', visualize=True)
    image_descriptors_single.append(fd)
    return image_descriptors_single

读取数据

def read_data(label2id):       # label2id为定义的标签
    X = []
    Y = []
    path ='./jaffe'
    for label in os.listdir(path):                 # os.listdir用于返回指定的文件夹包含的文件或文件夹的名字的列表,此处遍历每个文件夹
        for img_file in os.listdir(os.path.join(path, label)):             # 遍历每个表情文件夹下的图像
            image = cv2.imread(os.path.join(path, label, img_file))        # 读取图像
            if image is not None:
                result = preprocessing(image)
                X.append(result)                                    # 将读取到的所有图像的矩阵形式拼接在一起
                Y.append(label2id[label])                          # 将读取到的所有图像的标签拼接在一起
    return X, Y                                               # 返回的X,Y分别是图像的矩阵表达和图像的标签

划分数据

训练集/测试集=7/3

label2id = {'anger':0, 'disgust':1, 'fear': 2,'happiness':3,'neutral':4,'sadness':5,'surprise':6}
X, Y = read_data(label2id)
X_features = extract_hog_features(X)
X_train, X_test, Y_train, Y_test = train_test_split(X_features, Y, test_size=0.3, random_state=42)

网格搜索选取SVM参数

对poly核进行网格搜索

from sklearn.model_selection import KFold, GridSearchCV

gamma_range = np.logspace(-10,1,10)
coef0_range = np.linspace(0,5,10)
C_range = np.linspace(0.01,30,10)
degree_range = np.linspace(0,10,11)
param_grid = dict(gamma = gamma_range
                 ,coef0 = coef0_range
                 ,C = C_range
                 ,degree = degree_range
                 )
cv = KFold(n_splits=5,shuffle=True,random_state=520)
grid = GridSearchCV(SVC(kernel = "poly"),param_grid=param_grid, cv=cv, n_jobs = -1) # n_jobs = -1 调用所有线程
grid.fit(X_train, Y_train)
print("The best parameters are %s with a score of %0.5f" % (grid.best_params_, grid.best_score_))

对sigmoid核进行网格搜索

from sklearn.model_selection import KFold, GridSearchCV

gamma_range = np.logspace(-10,1,10)
coef0_range = np.linspace(0,5,10)
C_range = np.linspace(0.01,30,20)
param_grid = dict(gamma = gamma_range
                 ,coef0 = coef0_range
                 ,C = C_range
                 )
cv = KFold(n_splits=5,shuffle=True,random_state=520)
grid = GridSearchCV(SVC(kernel = "sigmoid"),param_grid=param_grid, cv=cv, n_jobs = -1) # n_jobs = -1 调用所有线程
grid.fit(X_train, Y_train)
print("The best parameters are %s with a score of %0.5f" % (grid.best_params_, grid.best_score_))

对rbf核进行网格搜索

from sklearn.model_selection import KFold, GridSearchCV

gamma_range = np.logspace(-10,1,10)
C_range = np.linspace(0.01,30,20)
param_grid = dict(gamma = gamma_range
                 ,C = C_range
                 )
cv = KFold(n_splits=5,shuffle=True,random_state=520)
grid = GridSearchCV(SVC(kernel = "rbf"),param_grid=param_grid, cv=cv, n_jobs = -1) # n_jobs = -1 调用所有线程
grid.fit(X_train, Y_train)
print("The best parameters are %s with a score of %0.5f" % (grid.best_params_, grid.best_score_))

对Linear核进行C取值搜索

C_range = np.linspace(0.01, 30, 30)
best_acc = -1
best_c = -1
for c in C_range:
    clf = SVC(kernel="linear", C=c)
    clf.fit(X_train, Y_train)
    acc = clf.score(X_test, Y_test)
    if acc > best_acc:
        best_acc = acc
        best_c = c
print("The best c is %0.5f with a score of %0.5f" % (best_c, best_acc))

结果分析:

在上面分别对多项式核(poly),双曲正切核(sigmoid),高斯径向基(rbf),线性核(linear)进行了网格搜索

poly的最佳准确率为75.7%,sigmoid的最佳准确率为70.4%,rbf的最佳准确率为72.4%,linear的最佳准确率为93.8%

因此选择线性核对该数据效果最佳,其中最佳的参数C选择为15.52。

探究各参数的影响

用rbf核探究gamma的影响

score = []
gamma_range = np.logspace(-10, 1, 50) #返回在对数刻度上均匀间隔的数字
for i in gamma_range:
    clf = SVC(kernel="rbf", gamma = i, cache_size=5000).fit(X_train,Y_train)
    score.append(clf.score(X_test, Y_test))
print(max(score), gamma_range[score.index(max(score))])
plt.plot(gamma_range, score)
plt.xlabel('gamma')
plt.ylabel('Accuracy')
plt.savefig('pt1.jpg')
plt.show()

用linear核探究C的影响

score = []
C_range = np.linspace(0.01, 30, 30)
for i in C_range:
    clf = SVC(kernel="rbf", C = i, cache_size=5000).fit(X_train,Y_train)
    score.append(clf.score(X_test, Y_test))
print(max(score), C_range[score.index(max(score))])
plt.xlabel('C')
plt.ylabel('Accuracy')
plt.savefig('pt2.jpg')
plt.plot(C_range, score)
plt.show()

参数c影响了支持向量与决策平面之间的距离,c越大,分类越严格,不能有错误;c越小,意味着有更大的错误容忍度。

参数gamma是对低维的样本进行高度度映射,gamma值越大映射的维度越高,训练的结果越好,但是越容易引起过拟合,即泛化能力低。

和其它方式进行对比

线性核SVM(前面筛选出最好的C=15.52)

svm = SVC(C = 15.52, kernel='linear')
svm.fit(X_train, Y_train)
Y_predict = svm.predict(X_test)
acc = accuracy_score(Y_test, Y_predict)
print('SVM准确率为: ', acc)

KNN准确率

knn = KNeighborsClassifier(n_neighbors=1) # k取1,最近邻准确率较高
knn.fit(X_train,Y_train)
Y_predict = knn.predict(X_test)
acc = accuracy_score(Y_test, Y_predict)
print('KNN准确率为: ', acc)

决策树准确率

tree_D = DecisionTreeClassifier()
tree_D.fit(X_train, Y_train)
Y_predict = tree_D.predict(X_test)
acc = accuracy_score(Y_test, Y_predict)
print('决策树准确率为: ', acc)

逻辑回归准确率

logistic = LogisticRegression()
logistic.fit(X_train, Y_train)
Y_predict = logistic.predict(X_test)
acc = accuracy_score(Y_test, Y_predict)
print('逻辑回归准确率为: ', acc)

朴素贝叶斯准确率

mlt = GaussianNB()
mlt.fit(X_train, Y_train)
Y_predict = mlt.predict(X_test)
acc = accuracy_score(Y_test, Y_predict)
print('朴素贝叶斯准确率为: ', acc)

随机森林准确率

Forest = RandomForestClassifier(n_estimators=180,random_state=0)
Forest.fit(X_train, Y_train)
Y_predict = Forest.predict(X_test)
acc = accuracy_score(Y_test, Y_predict)
print('随机森林准确率为: ', acc)

SVM+Bagging准确率

from sklearn.ensemble import BaggingClassifier
from sklearn.metrics import accuracy_score
svc = SVC(C = 20, kernel='poly')
clf = BaggingClassifier(base_estimator=svc, n_estimators=20, max_samples=1.0, max_features=1.0, 
                        bootstrap=True,bootstrap_features=False, n_jobs=-1, random_state=1)
clf.fit(X_train, Y_train)
Y_predict = clf.predict(X_test)
acc = accuracy_score(Y_test, Y_predict)
print('SVM+Bagging准确率为: ', acc)

XGBoost准确率

from xgboost import XGBClassifier as XGBR
reg = XGBR(n_estimators=200
          ,learning_rate=0.1
          ,booster="gblinear"
          ).fit(X_train,Y_train,eval_metric=['logloss','auc','error'])
Y_predict = reg.predict(X_test)
acc = accuracy_score(Y_test, Y_predict)
print('XGBoost准确率为: ', acc)

各方法结果:

分类器最佳准确率
SVM93.75%
KNN85.94%
决策树40.63%
逻辑回归45.31%
朴素贝叶斯60.94%
随机森林65.63%
SVM+Bagging93.75%
XGBoost93.75%

绘制SVM分类结果的混淆矩阵

cm = confusion_matrix(Y_test, Y_predict)
xtick = ['anger', 'disgust', 'fear', 'happiness', 'neutral', 'sadness', 'surprise']
ytick = xtick

f, ax = plt.subplots(figsize=(7, 5))
ax.tick_params(axis='y', labelsize=15)
ax.tick_params(axis='x', labelsize=15)

seaborn.set(font_scale=1.2)
plt.rc('font', family='Times New Roman',size=15)
seaborn.heatmap(cm,fmt='g', cmap='Blues', annot=True, cbar=True,xticklabels=xtick, yticklabels=ytick, ax=ax)
plt.title('Confusion Matrix', fontsize='x-large')
f.savefig('./混淆矩阵.png')
plt.show()

尝试导入单张图片查看分类效果

这里选用准确率最高的SVM做分类器

svm = SVC(C = 15.52, kernel='linear')
svm.fit(X_train, Y_train)
from IPython.display import Image

path = './test_pic.jpg'
image = cv2.imread(path)
display(Image(path))
result = preprocessing(image)
X_Single = extract_hog_features_single(result)
#这里选择分类器的类别
predict = svm.predict(X_Single)
if predict == 0:
    print('angry')
elif predict == 1:
    print('disgust')
elif predict == 2:
    print('fear')
elif predict == 3:
    print('happy')
elif predict == 4:
    print('neutral')
elif predict == 5:
    print('sad')
elif predict == 6:
    print('surprise')
  • 10
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: 支持向量机(SVM)算法是一种用于分类和回归分析的机器学习方法,它在人脸识别中有着广泛的应用。 人脸识别的目标是通过学习和推断来识别和验证人脸的身份。SVM算法在人脸识别中的应用主要体现在两个方面:特征提取和分类器构建。 首先,在人脸识别中,特征提取是一个非常重要的步骤。SVM算法可以通过最小化分类误差来选择最佳的特征子集,从而在高维特征空间中找到最优的超平面。例如,可以使用主成分分析(PCA)技术提取人脸图像的最重要的特征,然后将这些特征用作SVM分类器的输入。SVM在特征选择中的优势在于它可以处理非线性问题,并且对于高维数据集具有较好的鲁棒性。 其次,SVM还可以用于构建分类器来实现人脸识别。通过学习一组已知身份的人脸图像,SVM可以建立一个分类模型,使得新的人脸图像能够被正确分类SVM分类器通过将人脸图像投影到一个高维特征空间中,将不同身份的人脸分开。在新的人脸图像投影到特征空间后,SVM分类器可以根据与已知身份的距离来判断其身份。 总之,支持向量机(SVM)算法通过特征提取和分类器构建来实现人脸识别。它可以选择最佳的特征子集,并根据已知身份的人脸图像建立一个分类模型,以实现对未知人脸图像的身份判断。SVM算法在人脸识别中具有较好的性能,广泛应用于安全技术、人机交互等领域。 ### 回答2: 支持向量机(Support Vector Machine,SVM)是一种常用于模式识别机器学习的算法,它也可以用于人脸识别。SVM算法通过将数据集映射到高维空间中,找出最佳的超平面来分类数据。 在人脸识别中,SVM算法的实现步骤如下: 1. 收集数据集:首先,需要收集一组已标记的人脸图像数据集,其中每个图像都标有是否为某个人的标签。 2. 预处理数据:预处理数据是为了让SVM算法更好地理解数据。可以使用一些图像处理技术,例如灰度化、直方图均衡化、人脸对齐等,以确保输入数据的一致性。 3. 特征提取:对于每个人脸图像,需要提取其特征向量作为输入给SVM算法。常用的特征提取方法包括主成分分析(PCA)、局部二值模式(LBP)等。 4. 构建模型:使用已标记的人脸图像数据集来训练SVM模型。训练过程中,SVM算法将寻找最佳的超平面,使得不同类别的人脸图像能够被正确地分类。 5. 测试和识别:使用未标记的人脸图像数据集来测试和识别。将测试图像的特征向量输入到已训练的SVM模型中,观察其分类结果,即可得到人脸的识别结果。 SVM算法在人脸识别中的优点包括:具有较好的泛化能力,对于低维数据也能有效地工作;可以避免陷入局部最优解;可以通过核函数实现非线性分类等。然而,SVM算法在大规模人脸识别任务中运行速度较慢,且训练时间较长,需要对大规模数据进行处理。因此,在实际应用中,还需要结合其他优化方法来提高SVM算法在人脸识别任务中的效率和准确性。 ### 回答3: 支持向量机(Support Vector Machine,SVM)是一种常用的机器学习算法,可用于人脸识别任务。 人脸识别是一种将输入的人脸图像与已知人脸进行比较的任务。SVM通过在一个高维特征空间中找到一个最优超平面来分隔不同类别的样本。在人脸识别中,SVM可以通过训练样本的特征向量,学习到一个分类模型来对新的人脸图像进行分类SVM人脸识别过程可以分为以下几个步骤: 1. 数据准备:收集人脸图像数据,并将其标记为不同的类别,例如不同的人物或不同的表情。 2. 特征提取:使用人脸图像进行特征提取,一种常用的方法是使用主成分分析(PCA)或局部二值模式(Local Binary Pattern)等算法提取人脸的特征向量。 3. 模型训练:将提取的特征向量和对应的标签输入到SVM算法中进行训练。SVM根据这些训练样本在特征空间中的分布情况,找到一个最优的超平面来划分不同类别的样本。 4. 人脸识别:将新的人脸图像进行特征提取,并输入到训练好的SVM模型中进行分类SVM根据输入图像在特征空间中的位置,判断其属于哪个类别,并输出对应的标签。 SVM算法在人脸识别中具有优点,例如可以通过调整核函数来适应不同类型的特征,具有较好的泛化能力和鲁棒性,适用于处理高维数据。然而,SVM算法也存在一些挑战,例如对大规模数据集的训练效率较低,并且对于噪声和异常值比较敏感。 总的来说,使用支持向量机算法实现人脸识别,需要准备数据、提取特征、训练模型和进行识别等步骤。通过适当选择特征和调整算法参数,可以提高人脸识别的准确性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zstar-_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值