TensorFlow自定义Sequence数据生成器训练时,标签列表转NumPy数组引发形状不兼容错误
TensorFlow自定义Sequence数据生成器训练时,标签列表转NumPy数组引发形状不兼容错误
看起来你的问题出在标签字典构建的缩进错误,以及生成batch标签时的数组转换方式上,我来一步步帮你排查和解决:
问题根源分析
你给出的错误提示说“请求的数组在1维后有不均匀的形状”,这说明batch_labels列表里的元素形状/类型不一致。看你构建labels_dict的代码:
for i, sid in enumerate(train_df['study_id']): labels_dict[str(sid)] = [] for con in conditions: # ... 标签赋值逻辑 ... labels_dict[str(sid)] = np.array(labels_dict[str(sid)], dtype=np.float32)
注意最后一行转换数组的代码缩进是在for i, sid循环的外面!这意味着只有最后一个study_id的标签会被转成NumPy数组,其他所有id的标签仍然是普通列表。当你的生成器收集batch标签时,列表里混合了列表和数组类型,np.array()无法处理这种混合,就会抛出形状不均匀的错误。
另外,也有可能部分study_id对应的条件数量不等于5,导致标签形状不一致,不过先解决缩进问题是首要的。
解决步骤
1. 修正标签字典的构建代码
把转换数组的代码缩进放到for i, sid循环内部,确保每个id的标签都被正确转成形状为(5, 3)的NumPy数组:
labels_dict = {} for i, sid in enumerate(train_df['study_id']): labels_dict[str(sid)] = [] for con in conditions: if train_df.loc[i, con] == 'normal_mild': labels_dict[str(sid)].append([1, 0, 0]) elif train_df.loc[i, con] == 'severe': labels_dict[str(sid)].append([0, 0, 1]) else: labels_dict[str(sid)].append([0, 1, 0]) # 修正缩进:每个sid的标签都转成数组 labels_dict[str(sid)] = np.array(labels_dict[str(sid)], dtype=np.float32)
2. 改进生成器中batch标签的转换方式
在__getitem__方法里,用np.stack()替代np.array()来生成batch标签数组,它更适合处理形状一致的数组列表,能确保生成(batch_size, 5, 3)的标准形状:
def __getitem__(self, index): # ... 现有代码 ... if self.labels_dict: # 用np.stack替代np.array batch_labels = np.stack(batch_labels, axis=0) return batch_images, batch_labels return batch_images
3. 可选:添加形状检查(调试用)
如果还是有问题,可以在生成器里临时添加形状检查,确认每个id的标签形状是否符合预期:
for id_ in batch_ids: # ... 图像处理代码 ... if self.labels_dict: label = self.labels_dict.get(id_) # 打印标签形状,确认是否都是(5,3) print(f"Study ID {id_} label shape: {label.shape}") batch_labels.append(label)
验证解决效果
修改完成后,你可以先运行以下代码测试生成器的输出形状:
data_x, data_y = next(iter(train_generator)) print(f"Input shape: {data_x.shape}") # 应该是(batch_size, num_img, 224, 224, 3) print(f"Label shape: {data_y.shape}") # 应该是(batch_size, 5, 3)
如果输出形状符合预期,再启动训练就不会报错了。
备注:内容来源于stack exchange,提问作者Kazi Md Abdullah Al Mubin
相关产品推荐
相关产品推荐

