基于MediaPipe关键点的MLP-GRU动作识别模型训练与验证精度极低问题求助
基于MediaPipe关键点的MLP-GRU动作识别模型训练与验证精度极低问题求助
看起来你在处理一个极具挑战性的动作识别任务——300个严重不平衡的类别,而且多数类别样本量极少,确实很棘手。结合你给出的模型代码和训练设置,我整理了几个可能的优化方向,希望能帮到你:
一、模型结构的核心问题排查
- 维度不匹配的硬编码问题:你的GRU层参数是硬编码的
input_size=150、hidden_size=50,但fc_pre的输出维度是fc_size,如果初始化时传入的fc_size不等于150,那么fs[:, i, :] = f这一步会出现维度不匹配的错误(或者静默地截断/填充),直接导致模型无法正确学习序列特征。建议把GRU的input_size改为self.fc_size,保持参数的一致性:self.rnn = nn.GRU(input_size=self.fc_size, hidden_size=self.hidden_size, num_layers=rnn_layers, batch_first=True) - GRU输出的错误使用:动作识别任务中,通常是用序列的最后一个时间步的隐藏状态来做分类(因为整个序列对应一个动作类别),而不是把所有时间步的输出都传入全连接层。你当前的代码会输出
(batch_size, seq_len, num_classes)的结果,和单标签的损失计算不匹配。应该修改forward函数的最后部分:# 取最后一个时间步的输出 outputs = outputs[:, -1, :] outputs = self.fc(outputs) - 初始化函数的语法错误:
_init_weights里的module.bias.data.zero_少了括号,应该是module.bias.data.zero_(),否则这行代码完全不会执行,偏置没有被初始化为0,会影响模型的初始收敛能力。
二、训练参数的优化调整
- 学习率过低:1e-6的学习率太小了,对于MLP+GRU的结构,这个学习率几乎无法推动参数更新。建议先尝试
1e-4或1e-5作为初始学习率,再搭配ReduceLROnPlateau学习率调度器,根据验证损失动态降低学习率:scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=3, factor=0.5) - 类别不平衡的进阶处理:WeightedRandomSampler只是在采样层面平衡了批次,但小类样本量太少(<20)还是很难学到有效特征。可以尝试:
- 对小类做数据增广(比如时间翻转、关键点加高斯噪声、随机裁剪序列)
- 用Focal Loss替代CrossEntropyLoss,降低大类样本的损失权重,让模型更关注小类
- 手动设置类别权重的WeightedCrossEntropyLoss,权重可以设为
1/num_samples_per_class的归一化值
三、数据与特征的有效性提升
- 关键点归一化:MediaPipe的原始关键点坐标是基于图像像素的,建议先对关键点做归一化处理:比如以骨盆(或身体中心)为原点,将所有关键点坐标转换为相对坐标,消除不同视频中人物大小、位置的差异,这能大幅提升特征的鲁棒性。
- 序列长度处理:如果输入的动作序列长度不一致,需要统一为固定长度(padding或截断),或者用
PackedSequence处理变长序列,否则模型无法学习到稳定的序列模式。 - 针对性数据增广:针对动作序列可以做这些增广:
- 时间维度:随机裁剪序列中间片段、时间反转(适用于对称动作)、随机重复少量帧
- 关键点维度:给坐标加小幅度高斯噪声、随机遮挡10%-20%的关键点
四、模型调试与验证技巧
- 简化模型先验证:先去掉GRU层,只用MLP训练,看看能不能达到基础精度(比如超过1%)。如果MLP都无法收敛,问题大概率出在数据处理或训练参数上;如果MLP能有一定精度,再逐步加入GRU调试。
- 监控类别级准确率:记录每个类别的训练/验证准确率,看看是不是只有大类能被正确分类,小类完全没有预测正确,这样能精准定位问题所在。
- 检查参数更新情况:训练几轮后,查看模型的参数(比如全连接层的权重)是否有变化,如果完全没变化,说明学习率太低或者梯度消失了。
备注:内容来源于stack exchange,提问作者peony
相关产品推荐
相关产品推荐

