TensorFlow加载自定义数据集报错:BatchDataset无reshape属性
问题代码存在3个核心逻辑错误
- 数据集加载路径配置错误:
image_dataset_from_directory默认会将传入路径下的每一级子文件夹识别为一个独立类别,你传入根目录./data/时,API会把train、test两个子文件夹当成两个类别,把两个目录下的所有图片混在一起加载,根本没有按预期拆分训练集、测试集,这也是日志里提示Found 13233 files belonging to 2 classes的原因。 - 返回值类型认知错误:该API返回的是
tf.data.BatchDataset对象,属于TensorFlow的数据集流水线实例,不是numpy数组,自然不支持numpy数组专属的.reshape()、.shape属性、.astype()这类方法,直接调用必然报错。 - 预处理逻辑不符合TensorFlow数据集设计逻辑:你写的逻辑是把所有数据一次性加载为大数组再做全局处理,这种方式内存开销极高,也没有利用
tf.data的流水线加速能力,处理大规模数据时效率极低。
修复方案
按照TensorFlow数据集的标准使用逻辑调整即可,不需要把数据集手动转成numpy数组:
- 修正加载路径,分别指向训练集、测试集的实际目录,同时在加载阶段就指定目标图像尺寸,省略后续reshape操作。如果你的任务是图像去噪这类不需要类别标签的任务,加上
label_mode=None关闭自动类别标签生成。# 加载训练集,直接指定train子目录 train_ds = tf.keras.utils.image_dataset_from_directory( './data/train/', seed=123, image_size=(raw_size, raw_size), # 加载时直接resize到目标尺寸 batch_size=batch_size, label_mode=None # 不需要类别标签时开启,避免返回多余的标签张量 ) # 加载测试集,直接指定test子目录 test_ds = tf.keras.utils.image_dataset_from_directory( './data/test/', seed=123, image_size=(raw_size, raw_size), batch_size=batch_size, label_mode=None ) - 用
Dataset.map()方法实现预处理流水线,把加噪声、归一化的逻辑封装成处理函数,批量作用在数据集上,同时开启预加载提升运行效率。def preprocess_batch(images): # 转换像素值类型,归一化到[-1, 1]区间作为干净图像标签 clean_imgs = tf.cast(images, tf.float32) clean_imgs = (clean_imgs / 127.5) - 1.0 # 按配置添加高斯噪声生成模型输入 noise = tf.random.normal( shape=tf.shape(clean_imgs), mean=0.0, stddev=0.2 # 对应原代码stdev=0.2、像素范围0-255的噪声强度 ) noisy_imgs = clean_imgs + noise # 裁剪噪声值到合法像素区间,避免数值越界 noisy_imgs = tf.clip_by_value(noisy_imgs, -1.0, 1.0) return noisy_imgs, clean_imgs # 应用预处理,构建最终可用的训练、测试数据集 train_dataset = train_ds.map( preprocess_batch, num_parallel_calls=tf.data.AUTOTUNE # 开启并行预处理 ).shuffle(buffer_size).prefetch(tf.data.AUTOTUNE) # 开启预取,减少IO等待 test_dataset = test_ds.map( preprocess_batch, num_parallel_calls=tf.data.AUTOTUNE ).prefetch(tf.data.AUTOTUNE)
如果你处理的是极小数据集,非要用numpy数组的方式操作,可以用
np.concatenate([x.numpy() for x in train_ds], axis=0)把BatchDataset里的所有批次拼接为完整numpy数组,之后就可以正常调用reshape、astype等方法,但数据量较大时这种方式会直接占满内存,不推荐使用。
内容的提问来源于stack exchange,提问作者mchd
相关产品推荐
相关产品推荐

