首次使用PyTorch搭建RNN实现6分类:输出尺寸选择与准确率计算异常
问题解答与代码修复
核心认知纠偏
你使用batch_first=True初始化RNN时,各层张量的形状规则为:
- RNN输入:
(批次大小, 序列长度, 单时间步特征维度) - RNN返回的
out:(批次大小, 序列长度, 隐藏层维度)—— 这个out是所有时间步的隐藏状态集合,不是单个输出。只有序列标注类任务(每个时间步对应一个标签)才需要用到全时间步的输出,单样本单标签分类任务只需要截取最后一个时间步的隐藏状态即可。
你看到的4411不是输入特征维度,是你的输入序列的时间步长度。
Q1:输出尺寸设置规则
你的任务是6分类,每个样本对应输出6个类别的得分,因此全连接层的输出尺寸必须设置为6,不能设为1。
你当前初始化的output_size=6是正确的,无需修改。
Q2:准确率计算与维度错误修复
你当前的维度问题根源有两个:
- 没有截取RNN最后一个时间步的输出,全连接层对所有时间步都做了映射,导致输出多了
序列长度维度 - 你的标签使用了One-Hot格式(形状4×6),但
CrossEntropyLoss要求标签为形状(批次大小,)的整数类别索引
修复步骤
- 修改
forward函数,截取最后一个时间步的输出:
def forward(self, x): batch_size = x.size(0) hidden = self.init_hidden(batch_size) out, hidden = self.rnn(x, hidden) # 新增:截取最后一个时间步的输出,形状从 (batch, seq_len, hidden_dim) 变为 (batch, hidden_dim) out = out[:, -1, :] out = self.fc(out) return out, hidden
修改后输出形状为(批次大小, 6),完全符合分类任务要求。
- 转换标签格式适配损失函数:
# 训练循环中,把One-Hot标签转为类别索引 labels = torch.argmax(labels, dim=1) # 如果你的原始标签取值为1-6,需要减1适配PyTorch从0开始的类别规则 # labels = labels - 1
- 准确率计算逻辑无需修改:
现在output形状为(4,6),torch.max(output.data, 1)会对每个样本的6个类别得分取最大值,得到的predicted形状为(4,),和处理后的标签形状完全匹配,计算逻辑正确。
修复后张量形状验证
- RNN原始输出:
(4, 4411, 24)→ 截取最后时间步后:(4,24)→ 全连接层输出:(4,6) - 标签:原
(4,6)→ 转索引后:(4,) - 预测值:
(4,)
所有维度对齐,损失计算、准确率统计都会正常运行。
内容的提问来源于stack exchange,提问作者moinudin
相关产品推荐
相关产品推荐

