ResNet50训练Indian Pines数据集出现张量形状不兼容报错
问题根因
报错本质是分类任务的样本粒度不对齐,属于数据预处理阶段的维度处理错误:
- 自定义ResNet50最终输出为单样本17类分类概率,形状为
(None, 17),对应单个训练样本输出17维softmax概率的预期逻辑 - 传入的训练标签保留了长度为14065的多余序列/空间维度,形状为
(None, 14065, 17),和模型输出的单样本粒度完全不匹配,导致categorical_crossentropy损失计算时无法做逐样本的概率对齐 - 该多余维度的典型来源:
- 高光谱数据展平时未筛选有效标注像素,直接对整幅Indian Pines图像做了one-hot编码,后续划分数据集时错误保留了整图的像素展平维度
- 维度调整环节未将邻域块/单像素拆分为独立训练样本,标签和输入的样本粒度没有和模型分类头的输出逻辑对齐
- ResNet50结构问题已排除(已确认模型最终输出形状为
(None,17),问题100%出在标签预处理逻辑)
修复步骤
- 全流程张量形状校验
在数据加载、训练测试集划分、one-hot编码、维度调整每个环节打印张量形状,重点确认:- 输入样本
X_train的第一维长度(样本数)必须和标签y_train第一维长度完全相等 - 标签
y_train不能存在长度为14065的中间维度,最终形状必须为(训练样本数, 17)
- 输入样本
- 修正标签预处理逻辑
Indian Pines数据集中标签0为未标注区域,不能纳入训练集,参考以下修正逻辑处理标签:
如果采用邻域块输入训练ResNet50(2D卷积模式),需要确保每个邻域块对应一个中心像素的标签,标签列表按块顺序展平后再做one-hot编码,禁止保留整图的空间维度。import numpy as np from tensorflow.keras.utils import to_categorical # 假设原始数据X_raw形状为(145,145,200),原始标签y_raw形状为(145,145) # 第一步:筛选所有带标注的像素位置 labeled_mask = y_raw != 0 labeled_indices = np.where(labeled_mask) # 第二步:提取对应样本和标签,标签映射到0-16共17个类别 X = X_raw[labeled_indices] y = y_raw[labeled_indices] - 1 # 第三步:one-hot编码,此时标签形状为(有效标注样本数, 17),无多余维度 y = to_categorical(y, num_classes=17) # 第四步:按比例划分训练测试集,划分后标签形状保持(子集样本数,17) - 拟合前强制校验
调用model.fit()前执行断言,提前拦截维度错误:assert len(model.output_shape) == 2 and model.output_shape[-1] == 17, "模型输出维度不符合17类分类要求" assert len(y_train.shape) == 2 and y_train.shape[-1] ==17, "标签存在多余维度,形状不符合要求" assert X_train.shape[0] == y_train.shape[0], "输入样本数和标签样本数不匹配"
验证方法
- 取小批量样本(如8个)做前向传播,确认
model.predict(X_train[:8]).shape == (8,17),且对应批次标签y_train[:8].shape == (8,17),两者形状完全一致 - 启动训练后损失函数可以正常计算,不再触发形状不兼容报错,正常打印epoch迭代日志
内容的提问来源于stack exchange,提问作者Eduard
相关产品推荐
相关产品推荐

