深度学习之基于卷积神经网络(VGG16)实现性别判别

无意间在kaggle上发现的一个数据集,旨在提高网络模型判别男女的准确率,博主利用迁移学习试验了多个卷积神经网络,最终的模型准确率在95%左右。并划分了训练集、测试集、验证集三类,最终在验证集上的准确率为93.63%.

1.导入库

import tensorflow as tf
import matplotlib.pyplot as plt
import os,PIL,pathlib
import pandas as pd
import numpy as np
from tensorflow import keras
from tensorflow.keras import layers,models
from tensorflow.keras import layers, models, Input
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Conv2D, Dense, Flatten, Dropout,BatchNormalization,Activation
from tensorflow.keras.layers import MaxPooling2D, AveragePooling2D, Concatenate, Lambda,GlobalAveragePooling2D
from tensorflow.keras import backend as K

# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

2.导入数据

kaggle上下载的原数据一共有20000+张,由于硬件原因,博主选取了4286张作为训练集和测试集,剩下的作为验证集。

data_dir = "E:/tmp/.keras/datasets/Man_Women/faces_test"
data_dir = pathlib.Path(data_dir)
img_count = len(list(data_dir.glob('*/*')))
print(img_count)

all_images_paths = list(data_dir.glob('*'))
all_images_paths = [str(path) for path in all_images_paths]
all_label_names = [path.split("\\")[6].split(".")[0] for path in all_images_paths]
print(all_label_names)
4286
['man', 'woman']
Found 4286 images belonging to 2 classes.

参数设置:

height = 224
width = 224
epochs = 15
batch_size = 32

3.训练集与测试集

按照8:2的比例划分训练集和测试集

train_data_gen = tf.keras.preprocessing.image.ImageDataGenerator(
    rescale=1./255,#归一化
    validation_split=0.2,
    horizontal_flip=True#进行水平翻转,作为数据增强
)

train_ds = train_data_gen.flow_from_directory(
    directory=data_dir,
    target_size=(height,width),
    batch_size=batch_size,
    shuffle=True,
    class_mode='categorical',
    subset='training'
)
test_ds = train_data_gen.flow_from_directory(
    directory=data_dir,
    target_size=(height,width),
    batch_size=batch_size,
    shuffle=True,
    class_mode='categorical',
    subset='validation'
)
Found 3430 images belonging to 2 classes.
Found 856 images belonging to 2 classes.

图片展示:

plt.figure(figsize=(15, 10))  # 图形的宽为15高为10

for images, labels in train_ds:
    for i in range(30):
        ax = plt.subplot(5, 6, i + 1)
        plt.imshow(images[i])
        plt.title(all_label_names[np.argmax(labels[i])])
        plt.axis("off")
    break
plt.show()

深度学习之基于卷积神经网络(VGG16)实现性别判别_第1张图片

3.迁移学习VGG16网络

base_model = tf.keras.applications.VGG16(include_top=False, weights="imagenet",input_shape=(height,width,3),pooling = 'max')
x = base_model.output
x = tf.keras.layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001 )(x)
x = tf.keras.layers.Dense(256, activation='relu')(x)
x = tf.keras.layers.Dropout(rate=.45, seed=123)(x)
output = tf.keras.layers.Dense(2, activation='softmax')(x)
model=Model(inputs=base_model.input, outputs=output)

设置优化器

# #设置优化器
# #起始学习率
init_learning_rate = 1e-4
lr_sch = tf.keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate=init_learning_rate,
    decay_steps=50,
    decay_rate=0.96,
    staircase=True
)
gen_optimizer = tf.keras.optimizers.Adam(learning_rate=lr_sch)

网络编译&&训练

model.compile(
    optimizer=gen_optimizer,
    loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
    metrics=['accuracy']
)

history = model.fit(
    train_ds,
    epochs=epochs,
    validation_data=test_ds
)

训练结果如下所示:
深度学习之基于卷积神经网络(VGG16)实现性别判别_第2张图片
最终的模型准确率为95%左右,在博主试验的这些网络模型中,VGG16的模型准确率是最高的。

4.混淆矩阵的绘制

网络保存:

model.save("E:/Users/yqx/PycharmProjects/Man_Women_Rec/model_.h5")

网络加载:

model = tf.keras.models.load_model("E:/Users/yqx/PycharmProjects/Man_Women_Rec/model.h5")

利用模型对验证集的数据进行测试:

plt.figure(figsize=(50,50))

    for images,labels in validation_ds:
        num = 0
        total = 0
        for i in range(64):
            total += 1
            ax = plt.subplot(8,8,i+1)
            plt.imshow(images[i])
            img_array = tf.expand_dims(images[i],0)

            pre = model.predict(img_array)
            if np.argmax(pre) == np.argmax(labels[i]):
                num += 1
            plt.title(all_label_names[np.argmax(pre)])
            plt.axis("off")

        print(total)
        print(num)
        break
    plt.suptitle("The acc rating of validation is:{}".format((num / total)))
    plt.show()

深度学习之基于卷积神经网络(VGG16)实现性别判别_第3张图片
绘制混淆矩阵:

from sklearn.metrics import confusion_matrix
import seaborn as sns
import pandas as pd
    # 绘制混淆矩阵
def plot_cm(labels, pre):
    conf_numpy = confusion_matrix(labels, pre)  # 根据实际值和预测值绘制混淆矩阵
    conf_df = pd.DataFrame(conf_numpy, index=all_label_names,
                               columns=all_label_names)  # 将data和all_label_names制成DataFrame
    plt.figure(figsize=(8, 7))

    sns.heatmap(conf_df, annot=True, fmt="d", cmap="BuPu")  # 将data绘制为混淆矩阵
    plt.title('混淆矩阵', fontsize=15)
    plt.ylabel('真实值', fontsize=14)
    plt.xlabel('预测值', fontsize=14)
    plt.show()


test_pre = []
test_label = []
for images, labels in validation_ds:
    for image, label in zip(images, labels):
        img_array = tf.expand_dims(image, 0)  # 增加一个维度
        pre = model.predict(img_array)  # 预测结果
        test_pre.append(all_label_names[np.argmax(pre)])  # 将预测结果传入列表
        test_label.append(all_label_names[np.argmax(label)])  # 将真实结果传入列表
    break  # 由于硬件问题。这里我只用了一个batch,一共128张图片。
plot_cm(test_label, test_pre)  # 绘制混淆矩阵

深度学习之基于卷积神经网络(VGG16)实现性别判别_第4张图片

5.测试验证集

model = tf.keras.models.load_model("E:/Users/yqx/PycharmProjects/Man_Women_Rec/model.h5")
model.evaluate(validation_ds)

最终结果如下所示:

716/716 [==============================] - 418s 584ms/step - loss: 0.5345 - accuracy: 0.9363
[0.5345107175451417, 0.936279]#loss值与acc率

模型准确率比较高。在kaggle上,看到有模型准确率在99%左右,路过的大佬可以试验一下。

努力加油a啊

你可能感兴趣的:(机器学习,神经网络,深度学习,人工智能)