Keras深度学习实战——使用卷积神经网络实现性别分类
Posted 盼小辉丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Keras深度学习实战——使用卷积神经网络实现性别分类相关的知识,希望对你有一定的参考价值。
Keras深度学习实战——使用卷积神经网络实现性别分类
0. 前言
在《卷积神经网络详解与实现》中,我们了解了卷积神经网络 (Convolutional Neural Network
, CNN
) 的工作原理以及 CNN
模型在解决图像识别问题中的优越性。在本节中,我们将通过构建性别分类模型来验证 CNN
模型性能,从而进一步加深对 CNN
工作原理的了解。
1. 数据集与模型分析
首先,我们需要了解本节用于性别分类的数据集,数据集取自 Celeb A,可以自行构建数据集,也可以下载使用此数据集,提取码:nql9
。CelebA
是一个大规模的人脸属性数据集,其中包含超过 20
万张名人图像,每张图像有 40
个属性注释。
接下来,我们定义用于性别分类的神经网络模型策略:
- 首先获取图像的数据集,并根据图像中人物的性别标记每个图像
- 我们使用的数据集中男性和女性图像分别具有约
8000
张图像 - 数据集准备完成后,我们将图像整形为相同大小,以便将其输入到
CNN
模型中 - 构建
CNN
模型,其中输出层具有1
个节点,用于输出0
或1
两种标签表示男性或女性 - 使用二分类交叉熵损失函数,并最小化损失值
2. 构建卷积神经网络实现性别分类
在本节中,我们将采用上一小节中定义的策略使用 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)——卷积神经网络详解与实现
以上是关于Keras深度学习实战——使用卷积神经网络实现性别分类的主要内容,如果未能解决你的问题,请参考以下文章