基于Xception预训练网络完成人脸图片识别

一.导包

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import pathlib

二.数据处理:

我的数据集一共是10个不同的面部数据

先对数据进行读取

data_dir =  r'C:\Users\hao\rgzn21sdxx\sjwl\数据集\face_data' # 文件夹的路径
data_dir = pathlib.Path(data_dir) # Path类是pathlib模块中的主要类,用于表示和操作文件和文件夹路径
img_count = len(list(data_dir.glob('./*/*.jpg'))) # 使用Path对象的glob()方法来查找特定类型的文件
print(img_count)

 img_count是总的数据量(电脑硬件不行,没有GPU)

获取标签名

all_images_paths = list(data_dir.glob('*')) # 查找data_dir文件夹中的所有文件和文件夹
all_images_paths = [str(path) for path in all_images_paths]
all_label_names = [path.split("\\")[7].split(".")[0] for path in all_images_paths] # 获得最后一个标签名
print(all_label_names)

拿到的所有文件夹标签名和我实际的文件标签是一样的

三.正文开始

一.设置超参数

height = 224  # 图片高度
width = 224   # 图片宽度
epochs =100   # 训练次数
batch_size = 128  # 每个训练批次中包含的样本数量为128

二.创建一个图像数据增强生成器对象

train_data_gen = tf.keras.preprocessing.image.ImageDataGenerator(
    rescale=1./255,  # 数据归一化
    rotation_range=45, # 随机旋转图像的角度范围为 -45 度到 +45 度。模拟图像在不同角度下的变化
    shear_range=0.2, # 随机剪切图像的错切变换范围为 -0.2 到 +0.2。模拟图像在不同错切程度下的变化
    zoom_range=0.2, # 随机缩放图像的尺度范围为 0.8 到 1.2。模拟图像在不同缩放程度下的变化
    validation_split=0.2, # 将数据集划分为训练集和验证集  训练与验证[8:2]
    horizontal_flip=True # 随机水平翻转图像。模拟图像在水平方向上的镜像变换
)

数据增强是一种通过对训练数据进行随机变换来扩充数据集的技术。它可以帮助模型更好地学习到数据的特征,提高模型的泛化能力和鲁棒性。

三.使用train_data_gen自动生成训练集与验证集

train_ds = train_data_gen.flow_from_directory(
    directory=data_dir, # 数据集所在的目录
    target_size=(height,width), # 图像的大小
    batch_size=batch_size, # 每次训练批次数据的大小
    shuffle=True, # 在每次训练时打乱数据
    class_mode='categorical', # 标签类型   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'
)

可以看到,程序自己将数据集分为了两个。训练数据集一共有49张图片,验证数据集一共有10张图片。(总共59张图片)

四.查看图片

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

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

五.使用Xception预训练

base_model = tf.keras.applications.Xception(weights = 'imagenet',include_top = False,pooling = 'max',input_shape = (height,width,3))
# weights='imagenet':表示使用预训练的 Xception 模型的权重
# include_top=False:表示不包括模型的顶部(全连接层)。这样做的目的是将 Xception 模型作为特征提取器使用,而不是作为一个完整的分类模型
# pooling='max':表示使用最大池化操作来汇集特征
# input_shape=(height, width, 3):表示输入图像的尺寸,其中 height 和 width 是图像的高度和宽度,3 表示图像的通道数(RGB 图像)
base_model.trainable = False#前面的参数设置为不可训练
input = base_model.input # 获取 Xception 模型的输出张量
x = tf.keras.layers.Dense(256,activation='relu')(base_model.output) #  将Xception模型的输出张量连接到一个全连接层
x = tf.keras.layers.Dense(128,activation='relu')(x)
output = tf.keras.layers.Dense(10,activation='sigmoid')(x)
model = tf.keras.models.Model(inputs = input,outputs = output) # input:利用Xception提取图像特征   output:输出自己训练的模型

六.利用Adam指定学习速率

# 设置初始学习率
initial_learning_rate = 1e-4 # 指定初始学习率

lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
        initial_learning_rate, # 开始训练时的学习率
        decay_steps=300, # 学习步长
        decay_rate=0.96, # 更新速率
        staircase=True) # 阶梯状的衰减

# 将指数衰减学习率送入优化器
optimizer = tf.keras.optimizers.Adam(learning_rate=lr_schedule)

七.编译模型

model.compile(
    optimizer = optimizer, # 优化器
    loss = "categorical_crossentropy",  # 使用交叉熵损失函数  用于多分类问题
    metrics = ['accuracy'] # 评估指标
)

8.训练模型

history = model.fit(
    train_ds, # 训练集
    validation_data = test_ds, # 验证集
    epochs = epochs # 训练次数
)

loss:模型在训练数据集上的损失函数值
accuracy:模型在训练数据集上的正确率
val_loss:模型在验证数据集上的损失函数值
val_accuracy:模型在验证数据集上的准确率

9.打印

plt.plot(history.history.get("loss"),label='loss')
plt.plot(history.history.get('val_loss'),label='val_loss')
plt.legend()

plt.plot(history.history.get("accuracy"),label='acc')
plt.plot(history.history.get('val_accuracy'),label='val_acc')
plt.legend()

 

 可以看到图像一直在震荡,这可能是数据量过小导致产生了过拟合

解决方法:在编译自己的Dense层时增加dropout层

四.模型验证

plt.figure(figsize=(50,50)) # 创建一个大小为 (50, 50) 的图像窗口,能够容纳更多的子图。
num = 0
for images,labels in train_ds: 
    for i in range(49):
        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]):  # 如果预测的和真值相同
            plt.title(all_label_names[np.argmax(pre)], fontsize=50)
        else:
            plt.title("False :"+str(all_label_names[np.argmax(pre)]), fontsize=50)
        if np.argmax(pre) == np.argmax(labels[i]):
            num += 1
        plt.axis("off")
    break
plt.suptitle("The Acc rating is:{}".format(num / 50), fontsize=100)
plt.show()

 可以看到最后验证准确率为96%,出现了False

结语:

总结一下深度学习的一般步骤为:

        1.创建模型

        2.编译模型

        3.训练模型

        4.验证模型

本博客仅作一个基于预训练网络进行图片分类识别的参考。就我自己而言:在进行训练前,一定要对数据进行处理,分清楚这是一个二分类还是多分类问题。激活函数应该使用哪一个,输出函数,以及超参数的设置等等。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值