TensorFlow搭建CNN报TypeError及数据集构建问题咨询
问题解答
1. 报错原因、修复方案及流程配置错误
报错根因与修复
抛出TypeError: only integer scalar arrays can be converted to a scalar index的直接原因是第一层卷积层的input_shape参数传值错误:
你写的input_shape=fetched_image_list[1:]是对整个图像张量做切片,取出的是从第1个样本开始的所有样本组成的4维张量,而Keras层的input_shape参数要求传入单张输入样本的维度元组,不需要带batch维度。
修复方式很简单,把该行参数替换为单样本维度即可:
tf.keras.layers.Conv2D(32, (3, 3), strides=(2,2), padding="same", dilation_rate=(1,1), input_shape=(128, 128, 3), activation='relu'),
流程中其他配置错误
- 数据类型冗余:从你打印的数据集信息可以看到,最终图像和标签都是
tf.float64类型,但你读取图像时已经显式转成了tf.float32,问题出在初始化image_list时用的np.empty(shape=(total, 128, 128, 3))默认生成float64类型的numpy数组,后续塞入float32的图像张量时会自动向上转成float64,凭空多占一倍内存,拖慢训练速度。初始化时指定dtype即可修复:np.empty(shape=(total, 128, 128, 3), dtype=np.float32)。 - 数据集构建代码缺失关键行:你贴出的第三步代码里没有定义
dataset的语句,直接打印dataset能出结果是因为你在其他运行单元提前执行过生成逻辑,独立运行该段代码会直接报变量未定义错误,需要补全数据集生成语句:dataset = tf.data.Dataset.from_tensor_slices((fetched_image_list, labels))。 - 输出层配置缺失:你模型最后一层
Dense(label_size)没有指定激活函数,如果你的任务是回归任务(预测连续值)可以直接输出,但如果是多标签分类任务需要加sigmoid激活,单标签多分类任务需要加softmax激活,要根据实际任务目标补全,否则输出值范围和标签不匹配会导致训练不收敛。
2. 数据集组装流程评估
你当前的流程能生成可用的TensorSliceDataset,但存在几个明显的效率和合理性问题:
- 中间存储方式效率低:把所有图像转成numpy数组存pkl文件的IO效率很差,pkl格式不适合大规模图像数据存储,完全可以跳过手动循环读图存数组的步骤,直接把所有文件路径和对应标签喂给
tf.data.Dataset,用内置的图像解码、resize接口做批量处理,省去中间pkl文件的读写开销。 - 缺少必要的数据拆分和数据集预处理:你现在把100个样本全部作为训练集,没有拆分验证集,无法在训练过程中监控模型泛化能力;同时生成Dataset后没有做
shuffle(打乱)、batch(分批次)、prefetch(预加载)操作,训练时单样本喂入梯度波动大,IO和计算没有并行,训练速度会很慢。 - 存在隐式类型转换风险:你存标签的时候如果是普通Python列表转存pkl,加载后是numpy数组默认float64类型,和图像的float32类型不匹配,训练时TensorFlow会自动做类型转换,也会带来额外开销,加载标签后最好显式转成
np.float32类型。
内容的提问来源于stack exchange,提问作者TerrySoki
相关产品推荐
相关产品推荐

