一、问题
试利用机器学习包中的人脸识别数据集,构建支持向量识别模型和卷积神经网络识别模型。其中,数据集的获取方式参考如下:
import sklearn.datasets
a=sklearn.datasets.fetch_olivetti_faces()
数据a为一个字典。本数据集包括40个人,每个人采集10张人脸图片,图片大小为6464像素的灰度图片,像素值已经归一化处理。data数据集为400张人脸图片,按一维数组展平的全像素数据集,是一个二维数组。images为400张人脸图片,按原始像素矩阵6464的数据集,是一个三维数组。target为400张人脸图片对应40个人的编号,即目标类别编号:0~39。
提示:支持向量机识别模型的输入特征可以使用全像素值,也可以对全像素进行特征提取,比如主成分分析提取综合特征或计算其他类型的特征。
二、基本思路
1.对于支持向量机首先提取出所需要的数据a.data和a.target,这里的支持向量机识别模型的输入特征使用全像素值,基于特征指标数据构造自变量 X,同样也获得了40张人脸的值并构造为因变量y,按照 80%训练、20%测试,构 建训练数据集和测试数据集,并利用支持向量机模型进行训练与预测,并计算预测准确率。
2.对于卷积神经网络首先提取出所需要的数据a.images和a.target,对模型输入数据(X)和输出数据(Y)按 80%训练、20%测试, 随机划分训练集和测试集,我们采用TensorFlow2.0中的keras模块下的堆叠模型,构建多层卷积神经网络模型。 其堆叠顺序一般为:输入层—隐含层(一个或多个卷积层和池化层的组合) -输出层(展平层、 全连接层和输出层)。其一般理解为:输入层主要确定网络的输入数据形态,隐含层主要是 对输入数据提取特征(卷积)并降维(池化)处理,输出层即对降维处理后的特征数据按照 网络输出要求进行一维向量化(展平)处理,并通过类似一般神经网络的方式进行全连接并 输出预测结果。
三、程序(Python)
1.基于支持向量机的人脸识别模型
#数据a为一个字典。
#本数据集包括40个人
#每个人采集10张人脸图片,图片大小为6464像素的灰度图片,像素值已经归一化处理。
#data数据集为400张人脸图片,按一维数组展平的全像素数据集,是一个二维数组。
#images为400张人脸图片,按原始像素矩阵6464的数据集,是一个三维数组。
#target为400张人脸图片对应40个人的编号,即目标类别编号:0~39。
import sklearn.datasets
a=sklearn.datasets.fetch_olivetti_faces()
import numpy as np
X=a.data#data数据集为400张人脸图片,按一维数组展平的全像素数据集,是一个二维数组。
y=a.target#target为400张人脸图片对应40个人的编号,即目标类别编号:0~39。
targets = np.unique(a.target)#序号
target_names = np.array(["p%d" % t for t in targets]) #给每个人做标签
n_targets = target_names.shape[0]
n_samples, h, w = a.images.shape
print('Samples count:{}\nTarget count:{}'.format(n_samples, n_targets))
print('Image size:{}x{}\nData shape:{}'.format(w, h, X.shape))
from matplotlib import pyplot as plt
def plot_gallery(images, titles, h, w, n_row=2, n_col=5):
# 显示图片阵列:
plt.figure(figsize=(2*n_col, 2.2*n_row),dpi=140)
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.01)
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])
plt.axis('off')
n_row = 2
n_col = 6
sample_images = None
sample_titles = []
for i in range(n_targets):
people_images = X[y==i] # 注意这里传入i
people_sample_index = np.random.randint(0, people_images.shape[0], 1)
people_sample_image = people_images[people_sample_index, :]
if sample_images is not None:
sample_images = np.concatenate((sample_images, people_sample_image), axis=0)
else:
sample_images =people_sample_image
sample_titles.append(target_names[i]) # 这里target_names是在前面生成的标签
plot_gallery(sample_images, sample_titles, h, w, n_row, n_col)
#代码中X[y=i]可以选择除特定的所有照片,随机选出来的照片放在sample.images数组对象里,最后调用之前定义的函数把照片画出来。
#按80%训练,20%测试,构建训练数据集和测试数据集
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=4)
from sklearn.svm import SVC
clf = SVC(class_weight='balanced')#类标签平衡策略
clf.fit(x_train, y_train)
y1=clf.predict(x_test) #对测试数据进行预测,并获得预测结果
r=y1-y_test #预测值与真实值相减
v=len(r[r==0])/len(y1) #预测值与真实值相减为0,即预测准确,统计其准确率
print('预测准确率: ',v)
2.基于卷积神经网络的人脸识别模型(灰图)
#数据a为一个字典。
#本数据集包括40个人
#每个人采集10张人脸图片,图片大小为6464像素的灰度图片,像素值已经归一化处理。
#data数据集为400张人脸图片,按一维数组展平的全像素数据集,是一个二维数组。
#images为400张人脸图片,按原始像素矩阵6464的数据集,是一个三维数组。
#target为400张人脸图片对应40个人的编号,即目标类别编号:0~39。
import sklearn.datasets
a=sklearn.datasets.fetch_olivetti_faces()
import numpy as np
X = a.images
y = a.target
targets = np.unique(a.target)
target_names = np.array(["p%d" % t for t in targets]) #给每个人做标签
n_targets = target_names.shape[0]
n_samples, h, w = a.images.shape
print('Samples count:{}\nTarget count:{}'.format(n_samples, n_targets))
print('Image size:{}x{}\nData shape:{}'.format(w, h, X.shape))
from matplotlib import pyplot as plt
def plot_gallery(images, titles, h, w, n_row=2, n_col=5):
# 显示图片阵列:
plt.figure(figsize=(2*n_col, 2.2*n_row),dpi=140)
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.01)
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])
plt.axis('off')
n_row = 2
n_col = 6
sample_images = None
sample_titles = []
for i in range(n_targets):
people_images = X[y==i] # 注意这里传入i
people_sample_index = np.random.randint(0, people_images.shape[0], 1)
people_sample_image = people_images[people_sample_index, :]
if sample_images is not None:
sample_images = np.concatenate((sample_images, people_sample_image), axis=0)
else:
sample_images =people_sample_image
sample_titles.append(target_names[i]) # 这里target_names是在前面生成的标签
plot_gallery(sample_images, sample_titles, h, w, n_row, n_col)
#代码中X[y=i]可以选择除特定的所有照片,随机选出来的照片放在sample.images数组对象里,最后调用之前定义的函数把照片画出来。
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X,y, test_size=0.2, random_state=4)
from tensorflow.keras import layers, models
#构建堆叠模型
model = models.Sequential()
#设置输入形态
model.add(layers.Reshape((64,64,1),input_shape=(64,64)))
#第一个卷积层,卷积神经元个数为32,卷积核大小为3*,默认可省
model.add(layers.Conv2D(32, (3, 3),strides=(1,1),activation='relu'))
#紧接着的第一个池化层,2*2池化,步长为2,默认可省
model.add(layers.MaxPooling2D((2, 2),strides=2))
#第二个卷积层
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
#第二个池化层
model.add(layers.MaxPooling2D((2, 2)))
#第三个卷积层
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
#展平
model.add(layers.Flatten())
#全连接层
model.add(layers.Dense(64, activation='relu'))
#输出层
model.add(layers.Dense(40, activation='softmax'))#标签类型【0,40),需要注意
#打印获得模型信息
model.summary()
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=40)
model.evaluate(x_test, y_test,verbose=2)
yy=model.predict(x_test)#获得预测结果概率矩阵
y1=np.argmax(yy,axis=1) #获得最终预测结果,取概率最大的类标签
r=y1-y_test #预测结果与实际结果相减
rv=len(r[r==0])/len(r) #计算预测准确率
print('预测准确率: ',rv)