1. 项目概述人脸表情识别是人机交互、情感计算、智能监控、心理分析领域的核心基础任务。相较于物体分类、缺陷检测表情识别高度依赖细微面部纹理、眉眼嘴局部特征变化类间差异极小、极易混淆对模型特征提取能力与细节感知能力要求更高。本文基于PyTorch从零搭建专属CNN网络针对人脸灰度表情特征优化结构完整实现FER2013数据集七类表情分类全流程。项目包含精细化人脸数据预处理、针对性数据增强、表情专用CNN模型、完整训练验证、Loss/Acc曲线可视化、样本预测可视化、错例分析可视化维度为五套项目中最丰富可直接用于课程大作业、毕设、竞赛 baseline。2. 数据集介绍FER2013Facial Expression Recognition 2013是业界通用的人脸表情识别标准数据集广泛用于表情算法评测、情感计算模型训练数据来源于真实网络人脸图像包含光照变化、轻微侧脸、遮挡、肤色差异等真实场景干扰贴合实际落地场景。数据集核心参数样本总量35887张人脸图像图像尺寸统一48×48单通道灰度人脸图分类类别7类基础人脸表情具体标签愤怒、厌恶、恐惧、开心、平淡、悲伤、惊讶数据特点部分类别样本不均衡、恐惧与悲伤、平淡与悲伤类间相似度极高识别难度大任务属性细粒度情感分类依赖人脸微特征提取3. 环境依赖通用深度学习环境支持全平台CPU/GPU训练兼容前面所有项目环境。pip install torch torchvision matplotlib numpy -i https://pypi.tuna.tsinghua.edu.cn/simple4. 数据集预处理与专属数据增强针对人脸表情识别特性设计增强策略人脸无固定朝向、轻微平移缩放不改变表情类别因此采用轻微旋转、平移、水平翻转摒弃剧烈变换避免破坏五官相对位置导致表情语义失真。训练集强增强提升泛化测试集纯净标准化保证评测公平性。import torch import torchvision import torchvision.transforms as transforms from torch.utils.data import DataLoader import matplotlib.pyplot as plt import numpy as np # FER2013标准化参数 mean (0.5,) std (0.5,) # 人脸专属增强不破坏五官结构 train_transform transforms.Compose([ transforms.RandomHorizontalFlip(p0.5), transforms.RandomRotation(10), transforms.RandomAffine(degrees0, translate(0.1, 0.1)), transforms.ToTensor(), transforms.Normalize(mean, std) ]) test_transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean, std) ]) # 加载数据集 train_dataset torchvision.datasets.FER2013( root./fer2013, splittrain, downloadTrue, transformtrain_transform ) test_dataset torchvision.datasets.FER2013( root./fer2013, splittest, downloadTrue, transformtest_transform ) train_loader DataLoader(train_dataset, batch_size64, shuffleTrue, num_workers0) test_loader DataLoader(test_dataset, batch_size64, shuffleFalse, num_workers0) # 表情标签对应 emotion_labels [愤怒, 厌恶, 恐惧, 开心, 平淡, 悲伤, 惊讶] print(f训练集样本数{len(train_dataset)}) print(f测试集样本数{len(test_dataset)}) print(表情类别, emotion_labels) # 人脸样本可视化 def show_fer_sample(): data_iter iter(train_loader) images, labels next(data_iter) img torchvision.utils.make_grid(images[:8]) img img / 2 0.5 np_img img.numpy().transpose(1, 2, 0) plt.figure(figsize(12,6)) plt.imshow(np_img, cmapgray) plt.title(FER2013人脸表情样本) plt.axis(off) plt.show() show_fer_sample()5. 人脸表情专用CNN网络模型针对48×48小尺寸灰度人脸、细微表情特征设计专用深层CNN结构。多层卷积逐级提取五官边缘、纹理、五官相对位置特征搭配BN层加速收敛、Dropout抑制过拟合适配表情细粒度区分难点。网络参数量适中兼顾精度与训练速度专门适配人脸表情分类任务。import torch.nn as nn import torch.nn.functional as F class FER2013_CNN(nn.Module): def __init__(self, num_classes7): super(FER2013_CNN, self).__init__() # 特征提取模块1 self.conv1 nn.Conv2d(1, 64, kernel_size3, padding1) self.bn1 nn.BatchNorm2d(64) self.conv2 nn.Conv2d(64, 64, kernel_size3, padding1) self.bn2 nn.BatchNorm2d(64) self.pool1 nn.MaxPool2d(2, 2) self.drop1 nn.Dropout(0.3) # 特征提取模块2 self.conv3 nn.Conv2d(64, 128, kernel_size3, padding1) self.bn3 nn.BatchNorm2d(128) self.conv4 nn.Conv2d(128, 128, kernel_size3, padding1) self.bn4 nn.BatchNorm2d(128) self.pool2 nn.MaxPool2d(2, 2) self.drop2 nn.Dropout(0.4) # 特征提取模块3 self.conv5 nn.Conv2d(128, 256, kernel_size3, padding1) self.bn5 nn.BatchNorm2d(256) self.conv6 nn.Conv2d(256, 256, kernel_size3, padding1) self.bn6 nn.BatchNorm2d(256) self.pool3 nn.MaxPool2d(2, 2) self.drop3 nn.Dropout(0.5) # 分类头 self.fc1 nn.Linear(256 * 6 * 6, 1024) self.drop4 nn.Dropout(0.5) self.fc2 nn.Linear(1024, num_classes) def forward(self, x): x F.relu(self.bn1(self.conv1(x))) x F.relu(self.bn2(self.conv2(x))) x self.pool1(x) x self.drop1(x) x F.relu(self.bn3(self.conv3(x))) x F.relu(self.bn4(self.conv4(x))) x self.pool2(x) x self.drop2(x) x F.relu(self.bn5(self.conv5(x))) x F.relu(self.bn6(self.conv6(x))) x self.pool3(x) x self.drop3(x) x x.view(-1, 256 * 6 * 6) x F.relu(self.fc1(x)) x self.drop4(x) x self.fc2(x) return x # 设备适配 device torch.device(cuda if torch.cuda.is_available() else cpu) model FER2013_CNN().to(device) print(人脸表情识别模型初始化完成) print(model)6. 模型训练与验证针对表情数据集样本不均衡、难样本多的特点采用交叉熵损失函数Adam优化器配合适中学习率避免步长过大跳过最优解。严格区分训练、测试模式全程记录损失与精度数据保证实验可复现。import torch.optim as optim # 超参数 EPOCHS 50 LR 0.0009 criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.parameters(), lrLR) # 记录指标 train_loss_list [] train_acc_list [] test_loss_list [] test_acc_list [] for epoch in range(EPOCHS): # 训练 model.train() train_loss 0.0 train_correct 0 total_train 0 for images, labels in train_loader: images, labels images.to(device), labels.to(device) optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() train_loss loss.item() _, predicted torch.max(outputs.data, 1) total_train labels.size(0) train_correct (predicted labels).sum().item() avg_train_loss train_loss / len(train_loader) train_acc 100 * train_correct / total_train # 测试 model.eval() test_loss 0.0 test_correct 0 total_test 0 with torch.no_grad(): for images, labels in test_loader: images, labels images.to(device), labels.to(device) outputs model(images) loss criterion(outputs, labels) test_loss loss.item() _, predicted torch.max(outputs.data, 1) total_test labels.size(0) test_correct (predicted labels).sum().item() avg_test_loss test_loss / len(test_loader) test_acc 100 * test_correct / total_test train_loss_list.append(avg_train_loss) train_acc_list.append(train_acc) test_loss_list.append(avg_test_loss) test_acc_list.append(test_acc) print(f第{epoch1:2d}轮 | 训练损失:{avg_train_loss:.4f} | 训练精度:{train_acc:.2f}% | 测试损失:{avg_test_loss:.4f} | 测试精度:{test_acc:.2f}%) # 保存模型 torch.save(model.state_dict(), fer2013_cnn_best.pth) print(人脸表情识别模型保存成功)7. 超强可视化模块本项目特色包含训练曲线可视化 批量预测结果可视化 真实标签VS预测标签对比是五套项目中可视化效果最丰富、报告展示效果最好的一套。7.1 损失与精度曲线可视化plt.rcParams[font.family] [SimHei] plt.rcParams[axes.unicode_minus] False plt.figure(figsize(12, 5)) plt.subplot(1, 2, 1) plt.plot(train_loss_list, label训练损失, color#e74c3c) plt.plot(test_loss_list, label测试损失, color#3498db) plt.title(表情识别损失变化曲线) plt.xlabel(迭代轮数) plt.ylabel(损失值) plt.legend() plt.subplot(1, 2, 2) plt.plot(train_acc_list, label训练精度, color#e74c3c) plt.plot(test_acc_list, label测试精度, color#3498db) plt.title(表情识别准确率变化曲线) plt.xlabel(迭代轮数) plt.ylabel(准确率(%)) plt.legend() plt.tight_layout() plt.show()7.2 人脸表情预测结果对比可视化def visualize_prediction(): model.eval() data_iter iter(test_loader) images, labels next(data_iter) images images.to(device) with torch.no_grad(): outputs model(images) _, preds torch.max(outputs, 1) # 反归一化 images images.cpu() * 0.5 0.5 images images.numpy().transpose(0, 2, 3, 1) # 展示前12张预测结果 plt.figure(figsize(14, 8)) for i in range(12): plt.subplot(3, 4, i1) plt.imshow(images[i], cmapgray) true_label emotion_labels[labels[i]] pred_label emotion_labels[preds[i]] color green if true_label pred_label else red plt.title(f真实:{true_label}\n预测:{pred_label}, colorcolor) plt.axis(off) plt.tight_layout() plt.show() visualize_prediction()8. 创新优化与拓展方向引入注意力机制聚焦眉眼嘴关键表情区域抑制人脸背景无效信息添加混淆矩阵精准统计各类表情错分比例针对性优化难样本使用加权交叉熵损失解决FER2013样本不均衡问题引入学习率衰减提升模型后期收敛精度替换ResNet、VGG等经典网络对比不同骨干网络表情识别性能结合摄像头实时推理实现动态实时人脸表情识别系统9. 常见问题解决表情识别精度偏低该数据集本身难度高属于正常现象可通过注意力机制、迁移学习提升训练过拟合提升Dropout系数、加强数据增强、降低学习率数据集下载失败手动下载放入对应目录关闭网络代理重试预测图标签乱码代码内置中文字体适配直接运行即可正常显示