人脸识别模型搭建

本文详细介绍了如何使用Keras库构建一个基于ResNet50的CNN模型,涵盖了数据预处理、模型结构设计(包含卷积层、激活函数、池化、全连接层等)、模型训练、评估与保存的全过程。重点在于实践步骤和关键代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

建立一个基于CNN的人脸识别模型

在第一部分我们已经写完了一些数据预处理的方法,这些数据预处理的方法,在我们接下来依然要使用,无论是我们送入模型做训练的数据,还是用模型去识别的数据都需要进行预处理,这与我们使用框架提供给我们的数据是不同的

下面我们来一步步完成这个模型

首先导入我们需要的包

from keras.applications import ResNet50
from keras.models import Sequential,load_model
from keras.layers import Dense,Activation,Convolution2D,MaxPooling2D,Flatten,Dropout
import numpy as np
from dataSet import DataSet

keras.applications:Applications包里有很多深度学习经典模型,且有预训练好的权重。

这些模型可以轻松用于:

预测/特征提取/微调

这些预训练权重会在实例化模型时自动下载,且放置在~/.keras/models文件夹下。

对于图像识别任务,有下面这些模型可用:

Xception
VGG16
VGG19
ResNet50
InceptionV3
InceptionResNetV2
MobileNet
DenseNet
NASNet
MobileNetV2

这些模型都是大佬们已经做好的模型,下面会给大家做一个简单展示。

keras.layers

keras.layers:keras的核心网络层,包括一些搭建搭建模型的各个方法,包括下面这些方法

keras.layers.Dense()   #全连接层
keras.layers.Activation()  #激活层
keras.layers.Dropout()     #Dropout 包括在训练中每次更新时, 将输入单元的按比率随机设置为 0, 这有助于防止过拟合。
keras.layers.Flatten()     #将输入展平。不影响批量大小。
keras.layers.Reshape()      #将输入重新调整为特定的尺寸。
keras.layers.Permute()      #根据给定的模式置换输入的维度。在某些场景下很有用,例如将 RNN 和 CNN 连接在一起。
keras.layers.RepeatVector()     #将输入重复 n 次。
keras.layers.Lambda(function, output_shape=None, mask=None, arguments=None)     #将任意表达式封装为 Layer 对象。
keras.layers.ActivityRegularization(l1=0.0, l2=0.0)     #网络层,对基于代价函数的输入活动应用一个更新。
keras.layers.Masking(mask_value=0.0)        #使用覆盖值覆盖序列,以跳过时间步。

keras.layers.convolutional:keras的卷积层,对输入做卷积运算的层,根据数据的不同,有不同的卷积函数。遇到了再给大家做详细介绍

from dataSet import DataSet:这是我们在上一部分自己写的数据处理的方法,用于存储和格式化读取训练数据

开始创建模型:

1.创建一个模型类

class Model(object):
    FILE_PATH = r"model1.h5"   
    IMAGE_SIZE = 128    

    def __init__(self):
        self.model = None

模型类我们创建了两个类属性和一个初始化方法,初始化方法初始化了一个模型对象,类属性定义了两个我们在多个方法中都会用到的属性,分别为

FILE_PATH:模型进行存储和读取的地方

IMAGE_SIZE:模型接受的人脸图片尺寸

2.读取实例化后的DataSet类作为进行训练的数据源

def read_trainData(self,dataset):
    self.dataset = datasetdef read_trainData(self,dataset):
    self.dataset = dataset

2.建立一个CNN模型

创建一个建立模型的方法

def build_model(self):

创建模型

self.model = Sequential()

给模型添加一个卷积层

self.model.add(
    Convolution2D(
        filters=32,
        kernel_size=(5, 5),
        padding='same',
        dim_ordering='th',
        input_shape=self.dataset.X_train.shape[1:]
    )
)

参数包括,卷积核个数,尺寸

dim_ordering:‘tf’或’th’,该选项指定了Keras将要使用的维度顺序

添加激活层

self.model.add(Activation('relu'))

激活函数选取relu
激活函数

Sigmoid函数
tanh函数
Relu函数
Leaky ReLU函数(PReLU)
ELU (Exponential Linear Units) 函数
MaxOut函数

添加池化层

self.model.add(
    MaxPooling2D(
        pool_size=(2, 2),
        strides=(2, 2),
        padding='same'
    )
)

重复上面的步骤

self.model.add(Convolution2D(filters=64, kernel_size=(5, 5), padding='same'))
self.model.add(Activation('relu'))
self.model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'))

这个模型的数据较为复杂,增加深度可以改善效果

然后抹平之后进行全链接

self.model.add(Flatten())

self.model.add(Dense(512))
self.model.add(Activation('relu'))

全连接加激活层,重复了两次,一般最后一个,也就是输出层的激活函数会选怎softmax,其他地方大多会选用relu

self.model.add(Dense(self.dataset.num_classes))
self.model.add(Activation('softmax'))

最后进行分类

self.model.summary()

建立模型的完整代码

def build_model(self):
    self.model = Sequential()
    self.model.add(
        Convolution2D(
            filters=32,
            kernel_size=(5, 5),
            padding='same',
            dim_ordering='th',
            input_shape=self.dataset.X_train.shape[1:]
        )
    )

    self.model.add(Activation('relu'))
    self.model.add(
        MaxPooling2D(
            pool_size=(2, 2),
            strides=(2, 2),
            padding='same'
        )
    )

    self.model.add(Convolution2D(filters=64, kernel_size=(5, 5), padding='same'))
    self.model.add(Activation('relu'))
    self.model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'))
    

    self.model.add(Flatten())
    self.model.add(Dense(512))
    self.model.add(Activation('relu'))
    

    self.model.add(Dense(self.dataset.num_classes))
    self.model.add(Activation('softmax'))
    self.model.summary()

3.使用刚才的模型进行训练

def train_model(self):
    self.model.compile(
        optimizer='adam',  
        loss='categorical_crossentropy',
        metrics=['accuracy'])
    self.model.fit(self.dataset.X_train,self.dataset.Y_train,epochs=20,batch_size=20)

有很多可选的optimizer,这里给大家做的总结

梯度下降法(Gradient Descent)
1. 标准梯度下降法(GD)
2. 批量梯度下降法(BGD)
3. 随机梯度下降法(SGD)
动量优化法
1. Momentum
2. NAG
自适应学习率优化算法
1.AdaGrad算法
2.RMSProp算法
3.AdaDelta算法
4.Adam算法

损失函数

一、log对数损失函数(逻辑回归)
二、平方损失函数(最小二乘法, Ordinary Least Squares )
三、指数损失函数(Adaboost)
四、Hinge损失函数(SVM)

具体的optimizer(优化器)、loss(损失函数)可以进行不同选择

epochs、batch_size为可调的参数,epochs为训练多少轮、batch_size为每次训练多少个样本

4.resnet

除了自己建模型训练以外,我们也可以使用预训练模型训练自己的数据

def train_resnet_model(self):
    self.model = ResNet50(
        weights=None,
        classes=10
    )
    self.model.compile(optimizer='adam',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    self.model.fit(self.dataset.X_train, self.dataset.Y_train, epochs=20, batch_size=20)

只加载模型,不加载权重,由我们自己传入数据训练权重

5.评估模型

def evaluate_model(self):
    print('\nTesting---------------')
    loss, accuracy = self.model.evaluate(self.dataset.X_test, self.dataset.Y_test)
    print('test loss;', loss)
    print('test accuracy:', accuracy)

打印了一些关键信息,方便我们观察模型效果

6.保存模型

def save(self, file_path=FILE_PATH):
    print('Model Saved.')
    self.model.save(file_path)

7.加载模型

def load(self, file_path=FILE_PATH):
    print('Model Loaded.')
    self.model = load_model(file_path)

8.使用模型做预测

需要确保输入的img得是灰化之后(channel =1 )且 大小为IMAGE_SIZE的人脸图片

img = img.reshape((1, 1, self.IMAGE_SIZE, self.IMAGE_SIZE))
img = img.astype('float32')
img = img/255.0

测算一下该img属于某个label的概率

result = self.model.predict_proba(img)

找出概率最高的

max_index = np.argmax(result)

第一个参数为概率最高的label的index,第二个参数为对应概率

return max_index,result[0][max_index]

模型预测的完整代码

def predict(self,img):
    img = img.reshape((1, 1, self.IMAGE_SIZE, self.IMAGE_SIZE))
    img = img.astype('float32')
    img = img/255.0
    result = self.model.predict_proba(img) 
    max_index = np.argmax(result) 

最后我们整理一下所有部分,并写一个函数调用上面这个方法训练并保存一个模型

from keras.applications import ResNet50
from keras.models import Sequential,load_model
from keras.layers import Dense,Activation,Convolution2D,MaxPooling2D,Flatten,Dropout
import numpy as np
from dataSet import DataSet


class Model(object):
    FILE_PATH = r"model1.h5" 
    IMAGE_SIZE = 128   

    def __init__(self):
        self.model = None

    def read_trainData(self,dataset):
        self.dataset = dataset

    def build_model(self):
        self.model = Sequential()
        self.model.add(
            Convolution2D(
                filters=32,
                kernel_size=(5, 5),
                padding='same',
                dim_ordering='th',
                input_shape=self.dataset.X_train.shape[1:]
            )
        )
        self.model.add(Activation('relu'))
        self.model.add(
            MaxPooling2D(
                pool_size=(2, 2),
                strides=(2, 2),
                padding='same'
            )
        )
        self.model.add(Convolution2D(filters=64, kernel_size=(5, 5), padding='same'))
        self.model.add(Activation('relu'))
        self.model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'))
        
        self.model.add(Flatten())
        self.model.add(Dense(512))
        self.model.add(Activation('relu'))
        
        self.model.add(Dense(self.dataset.num_classes))
        self.model.add(Activation('softmax'))
        self.model.summary()


    def train_resnet_model(self):
        self.model = ResNet50(
            weights=None,
            classes=10
        )
        self.model.compile(optimizer='adam',
                      loss='categorical_crossentropy',
                      metrics=['accuracy'])
        self.model.fit(self.dataset.X_train, self.dataset.Y_train, epochs=20, batch_size=20)


    def train_model(self):
        self.model.compile(
            optimizer='adam',  
            loss='categorical_crossentropy', 
            metrics=['accuracy'])
        self.model.fit(self.dataset.X_train,self.dataset.Y_train,epochs=20,batch_size=20)

    def evaluate_model(self):
        print('\nTesting---------------')
        loss, accuracy = self.model.evaluate(self.dataset.X_test, self.dataset.Y_test)
        print('test loss;', loss)
        print('test accuracy:', accuracy)

    def save(self, file_path=FILE_PATH):
        print('Model Saved.')
        self.model.save(file_path)

    def load(self, file_path=FILE_PATH):
        print('Model Loaded.')
        self.model = load_model(file_path)

    def predict(self,img):
        img = img.reshape((1, 1, self.IMAGE_SIZE, self.IMAGE_SIZE))
        img = img.astype('float32')
        img = img/255.0
        result = self.model.predict_proba(img) 
        max_index = np.argmax(result)
        return max_index,result[0][max_index]

if __name__ == '__main__':
    dataset = DataSet(r'D:\AI\face_recg\dataset1')
    model = Model()
    model.read_trainData(dataset)
    model.build_model()
    model.train_model()
    # model.train_resnet_model()
    model.evaluate_model()
    model.save()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值