在《卷积神经网络详解与实现》中,我们了解了卷积神经网络 (Convolutional Neural Network
, CNN
) 的工作原理以及 CNN
模型在解决图像识别问题中的优越性。在本节中,我们将通过构建性别分类模型来验证 CNN
模型性能,从而进一步加深对 CNN
工作原理的了解。
首先,我们需要了解本节用于性别分类的数据集,数据集取自 Celeb A,可以自行构建数据集,也可以下载使用此数据集,提取码:nql9
。CelebA
是一个大规模的人脸属性数据集,其中包含超过 20
万张名人图像,每张图像有 40
个属性注释。
接下来,我们定义用于性别分类的神经网络模型策略:
8000
张图像CNN
模型中CNN
模型,其中输出层具有 1
个节点,用于输出 0
或 1
两种标签表示男性或女性在本节中,我们将采用上一小节中定义的策略使用 Keras
实现性别分类模型。
8000
张男性图像和 8000
张女性图像:import numpy as np
from skimage import io
from glob import glob
from matplotlib import pyplot as plt
import cv2
x = []
y = []
for i in glob('man_woman/a_resized/*.jpg')[:8000]:
try:
image = io.imread(i)
x.append(image)
y.append(0)
except:
continue
for i in glob('man_woman/b_resized/*.jpg')[:8000]:
try:
image = io.imread(i)
x.append(image)
y.append(1)
except:
continue
在以上代码中,使用 glob
方法获取目录下相应图片,使用 skimage
读取相对应的图像,为了对数据集有所了解,我们查看数据集图像:
plt.subplot(221)
plt.imshow(x[0])
plt.title('Male')
plt.subplot(222)
plt.imshow(x[1])
plt.title('Male')
plt.subplot(223)
plt.imshow(x[-1])
plt.title('FeMale')
plt.subplot(224)
plt.imshow(x[-2])
plt.title('FeMale')
plt.show()
x2 = []
for i in range(len(x)):
img = cv2.cvtColor(x[i], cv2.COLOR_BGR2GRAY)
img2 = cv2.resize(img, (64, 64))
x2.append(img2)
plt.subplot(221)
plt.imshow(x[0])
plt.title('Original')
plt.subplot(222)
plt.imshow(x2[0], cmap='gray')
plt.title('Transformed')
plt.subplot(223)
plt.imshow(x[-1])
plt.title('Original')
plt.subplot(224)
plt.imshow(x2[-1], cmap='gray')
plt.title('Transformed')
plt.show()
为了简单起见,在以上代码中,我们将彩色图像转换为灰度图像。此外,我们将图像尺寸调整为较小的形状 (64 x 64 x 1)
,结果如下:
reshape
方法进行整形,使其可以作为 CNN
网络输入形状:# 输入的值介于0到255之间,因此对其进行缩放
x2 = np.array(x2) / 255.
x2 = x2.reshape(x2.shape[0], x2.shape[1], x2.shape[2], 1)
y = np.array(y)
将输入和输出数组拆分为训练和测试数据集:
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x2, y, test_size=0.2)
# 打印训练和测试集形状
print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)
打印训练和测试集形状,输出数组的形状如下:
(6400, 64, 64, 1) (1600, 64, 64, 1) (6400,) (1600,)
在以上数组形状中,第一个维度表示图片数量,x_train
和 x_test
中的第 2
和第 3
维度表示图片的尺寸,而最后一个维度表示图片的通道数,因为我们使用灰度图像,因此维度为 1
。
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
from keras.models import Sequential
model = Sequential()
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu',input_shape=(64,64,1)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, kernel_size=(3, 3), activation='relu',padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(256, kernel_size=(3, 3), activation='relu',padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(512, kernel_size=(3, 3), activation='relu',padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(1024, kernel_size=(3, 3), activation='relu',padding='same'))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.summary()
该模型的简要架构信息输出如下:
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 48, 48, 64) 640
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 24, 24, 64) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 24, 24, 128) 73856
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 128) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 12, 12, 256) 295168
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 6, 6, 256) 0
_________________________________________________________________
conv2d_3 (Conv2D) (None, 6, 6, 512) 1180160
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 3, 3, 512) 0
_________________________________________________________________
conv2d_4 (Conv2D) (None, 3, 3, 1024) 4719616
_________________________________________________________________
flatten (Flatten) (None, 9216) 0
_________________________________________________________________
dense (Dense) (None, 100) 921700
_________________________________________________________________
dense_1 (Dense) (None, 1) 101
=================================================================
Total params: 7,191,241
Trainable params: 7,191,241
Non-trainable params: 0
_________________________________________________________________
可以看到,卷积层输出中的通道数将等于该层中指定的卷积核数。此外,卷积层后使用了池化层,以减小图片尺寸。
adam
优化器最小化损失值,如下所示:model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['acc'])
history = model.fit(x_train, y_train,
batch_size=32,
epochs=50,
verbose=1,
shuffle=True,
validation_data = (x_test, y_test))
拟合模型后,我们可以看到构建的卷积神经网路在预测数据集图像中识别性别的准确率可以到达 90%
左右。
模型的分类准确率可以通过以下方法进一步提高:
CNN
网络的深度,或使用更高性能的网络架构Dropout
避免过度拟合本节中,我们构建并训练了一个用于进行性别分类的卷积神经网路模型,并未使用任何提升 CNN
模型的优化技术,CNN
模型就可以以 90%
以上的准确率完成性别分类任务,充分展示了 CNN
模型的强大拟合能力。
Keras深度学习实战(1)——神经网络基础与模型训练过程详解
Keras深度学习实战(2)——使用Keras构建神经网络
Keras深度学习实战(7)——卷积神经网络详解与实现