Press "Enter" to skip to content

Keras深度学习——使用卷积神经网络实现性别分类

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

 

前言

 

《卷积神经网络详解与实现》 中,我们了解了卷积神经网络 ( Convolutional Neural Network , CNN ) 的工作原理以及 CNN 模型在解决图像识别问题中的优越性。在本节中,我们将通过构建性别分类模型来检测 CNN 模型性能,从而进一步加深对 CNN 工作原理的了解。

 

数据集与模型分析

 

实现我们了解本节所用数据集,数据集取自Celeb A ,可以自行构建数据集,也可以下载使用此数据集,提取码:nql9。 CelebA 是一个大规模的人脸属性数据集,其中包含超过 20 万张名人图像,每张图像有 40 个属性注释。 接下来,我们定义用于性别分类的神经网络模型策略:

首先获取图像的数据集,并根据图像中人物的性别标记每个图像
我们使用的数据集中男性和女性图像分别具有约 8000 张图像
数据集准备完成后,我们将图像整形为相同大小,以便将其输入到 CNN 模型中
构建 CNN 模型,其中输出层具有 1 个节点,用于输出 01 两种标签表示男性或女性
使用二分类交叉熵损失函数,并最小化损失值

构建卷积神经网络实现性别分类

 

在本节中,我们将采用上一小节中定义的策略使用 Keras 实现性别分类模型。

 

 

    1. 首先,加载数据集并检查其内容,从数据集中取

8000

    1. 张男性图像和

8000

    1. 张女性图像:

 

 

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()

 

 

 

    1. 创建输入和输出数组:

 

 

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) ,结果如下:

 

 

 

    1. 创建训练和测试数据集。首先,我们将输入和输出列表转换为数组,然后对输入进行归一化,并使用

reshape

    1. 方法进行整形,使其可以作为

CNN

    1. 网络输入形状:

 

 

# 输入的值介于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_trainx_test 中的第 2 和第 3 维度表示图片的尺寸,而最后一个维度表示图片的通道数,因为我们使用灰度图像,因此维度为 1

 

 

    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
_________________________________________________________________

 

可以看到,卷积层输出中的通道数将等于该层中指定的卷积核数。此外,卷积层后使用了池化层,以减小图片尺寸。

 

 

    1. 然后,我们编译模型,使用二进制交叉熵损失(因为输出中只包括两个类),使用

adam

    1. 优化器最小化损失值,如下所示:

 

 

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['acc'])

 

 

    1. 最后,拟合模型:

 

 

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

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。