本次案例我们讲解的是如何使用飞桨动态图版本实现一个表情分类任务。在本次案例中,我们可以简单地将人脸表情分类视为一个图像分类任务。也就是说,向模型输入一张表情图像,模型能够对表情的类别进行识别并输出类别结果,如下图所示。
案例中使用的数据均来自互联网公开数据集。该数据集中包含positive和negative两种表情,共7200余张图片,图片尺寸为64*64(大部分为单通道图像,个别图像为3通道)的灰度图像,在实践过程中,我们将数据集按照1:9的比例划分为验证集和训练集。数据图像示例如下。
在本实践中,我们采用的是卷积神经网络(Convolution Neural Network,简称CNN)。卷积神经网络(CNN)是深度学习的一个经典网络模型,它可以看作是深度神经网络(DNN)的一种特殊形式。卷积神经网络主要由卷积层、池化层和全联接层三种网络层构成,在卷积层与全联接层后通常会接激活函数。
CNN网络结构示例如下图所示。
卷积层会对输入的特征图(或原始数据)进行卷积操作,输出卷积后产生的特征图。卷积层是卷积神经网络的核心部分。输入到卷积层的特征图是一个三维数据,不仅有宽、高两个维度,还有通道维度上的数据,因此输入特征图和卷积核可用三维特征图表示。如下图所示,对于一个(3,6,6)的输入特征图,卷积核大小为(3,3,3),输出大小为(1,4,4),当卷积核窗口滑过输入时,卷积核与窗口内的输入元素作乘加运算,并将结果保存到输出相应的位置。
上图中卷积操作输出了一张特征图,即通道数为1的特征图,而一张特征图包含的特征数太少,在大多数计算机视觉任务中是不够的,所以需要构造多张特征图,而输入特征图的通道数又与卷积核通道数相等,一个卷积核只能产生一张特征图,因此需要构造多个卷积核。在RGB彩色图像上使用多个卷积核进行多个不同特征的提取,示意图如下:
池化层
池化层的作用是对网络中的特征进行选择,降低特征数量,从而减少参数数量和计算开销。最常见的池化操作为最大池化或平均池化。如下图所示,采用了最大池化操作,对邻域内特征点取最大值作为最后的特征值。
最常见的池化层使用大小为2×2,步长为2的滑窗操作,有时窗口尺寸为3,更大的窗口尺寸比较罕见,因为过大的滑窗会急剧减少特征的数量,造成过多的信息损失。
了解了CNN的网络结构后,接下来我们将在AI Studio平台上利用飞桨动态图搭建一个简单的CNN网络模型,实现表情分类任务。
步骤1:导入所需的包和参数配置
##导入所需的包
import os
import zipfile
import random
import json
import cv2
import numpy as np
from PIL import Image
import paddle
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import Pool2D,Conv2D
import matplotlib.pyplot as plt
'''
参数配置
'''
train_parameters = {
"input_size": [1, 32, 32], #输入图片的shape
"class_dim": -1, #分类数
"src_path":"data/data33766/face_data.zip", #原始数据集路径
"target_path":"/home/aistudio/data/dataset", #要解压的路径
"train_list_path": "./train_data.txt", #train_data.txt路径
"eval_list_path": "./val_data.txt", #eval_data.txt路径
"label_dict":{}, #标签字典
"readme_path": "/home/aistudio/data/readme.json", #readme.json路径
"num_epochs": 100, #训练轮数
"train_batch_size": 32, #训练时每个批次的大小
"learning_strategy": { #优化函数相关的配置
"lr": 0.001 #超参数学习率
}
}
步骤2:数据准备
在AI Studio项目中,数据集是以压缩包的形式挂载在data/data33766目录下的,我们定义unzip_data()函数对数据进行解压缩,代码如下:
def unzip_data(src_path,target_path):
'''
解压原始数据集,将src_path路径下的zip包解压至data/dataset目录下
'''