踩坑记录: Pytorch框架下--- 从零使用卷积神经网络实现人脸面部表情识别 (基于连续维度)

之前一直在自学深度神经网络的知识,在跟着书本一步一步走的时候,感觉每一个思路,每一句代码都特别容易,实现思路清晰明了,实验代码简单易懂。但当我真正课题需要用到的时候,想跳出书本的框架,自行实现并通透其中的过程时,一上手真的是泪流满面,书本上的两三句话可能在你实验中会遇到各种各样头大的问题。。。不过还好,自己从头到尾实现一遍,理解的深刻程度也是看书不能比的,下面记录一下我之前的笔记,欢迎交流指导...
摘要由CSDN通过智能技术生成

之前一直在自学深度神经网络的知识,在跟着书本一步一步走的时候,感觉每一个思路,每一句代码都特别容易,实现思路清晰明了,实验代码简单易懂。但当我真正课题需要用到的时候,想跳出书本的框架,自行实现并通透其中的过程时,一上手真的是泪流满面,书本上的两三句话可能在你实验中会遇到各种各样头大的问题。。。
在这里插入图片描述
不过还好,自己从头到尾实现一遍,理解的深刻程度也是看书不能比的,下面记录一下我之前的笔记,欢迎交流指导

基于深度学习的表情识别

废话不多说。出发点呢,是因为想自行实现一下,看别人代码总是看得吃力,自己写一遍就印象深刻了,下面让我们来从0开始吧,这次真的是从0开始,所以前期的准备工作都要做一遍。我的实验呢是基于连续维度下的面部表情识别,注意是连续维度下(arousal-valence维度),和以往的基于分类的面部表情识别(七种或N种离散表情)在网络框架上可能有些不同,然后具体的流程可能有:

1. 数据集准备,处理
2. 网络框架自定义
3. 定义训练、测试函数
4. 在笔记本上只要代码可以跑通,就搬移到带GPU的服务器上,将代码改成在GPU上运行

先一个一个分析,最终完整的测试代码,放在文章最后。

数据集、样本选择

首先,实验基于AffectNet数据库,标注包括特征点、离散表情类、AU单元、A/V标注值等等。 这个数据库的话感觉是表情识别数据库中样本量最广,表情类别最多的数据库了吧,图像都是在网上爬的,, 和电影桥段那种数据库可不一样,感觉基于这个数据库比其他的都有挑战性。 因为是小测验,我决定选取就10000个样本吧,然后基于连续维度应该是针对arousal维度和valence维度,但这两个描述维度,涉及到要给网络定义两个不同的损失函数去分别进行学习,所以我只用1个arousal标签,省时省力。

在arousal标签值 -1 到 1之间,我将其划分为10个区间,每个区间选取1000个样本。关于对数据记得划分,以及如何选取样本,可以参考我很早之前这篇文章Affectnet数据集 按标签值对图像进行分类,然后将分成的10个CSV文件合并,合并代码很简单,可以在关于划分数据库时及处理CSV文件的问题研究记录描述这篇文章找到。
最终存储的CSV文件,包含10000个样本的地址目录,以及其arousal标注,像这样就搞定了,方便之后的实验进行:
在这里插入图片描述

网络框架定义

因为我的网络输出输出是连续值,不是分类值,所以网络的最终输出层应该选择线性回归层,让它输出连续的预测值。**同时这里要注意:**损失函数要采用回归类的损失函数(如MSEloss等)。
然后网络框架定义,随便定义了一个小网络(仅供参考,这是随便写的,为了保证识别准确率后期自己进行了修改),如下:

class FaceCNN(nn.Module):
    # 初始化网络结构
    def __init__(self):
        super(FaceCNN, self).__init__()
        
        # 第一次卷积、池化
        self.conv1 = nn.Sequential(
            # 输入通道数in_channels,输出通道数(即卷积核的通道数)out_channels,卷积核大小kernel_size,步长stride,对称填0行列数padding
            # input:(bitch_size, 1, 48, 48), output:(bitch_size, 64, 48, 48), (48-3+2*1)/1+1 = 48
            nn.Conv2d(in_channels=1, out_channels=64, kernel_size=3, stride=1, padding=1), # 卷积层
            nn.BatchNorm2d(num_features=64), # 归一化
            nn.ReLU(inplace=True), # 激活函数
            # output(bitch_size, 64, 24, 24)
            nn.MaxPool2d(kernel_size=2, stride=2), # 最大值池化
        )
        
        # 第二次卷积、池化
        self.conv2 = nn.Sequential(
            # input:(bitch_size, 64, 24, 24), output:(bitch_size, 128, 24, 24), (24-3+2*1)/1+1 = 24
            nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(num_features=128),
            nn.ReLU(inplace=True),
            # output:(bitch_size, 128, 12 ,12)
            nn.MaxPool2d(kernel_size=2, stride=2
  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值