You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用image_dataset_from_directory遇TensorFlow不可分片数据集报错求助

问题描述

使用image_dataset_from_directory构建数据集,结合MirroredStrategy多GPU训练CNN时,出现以下警告并导致脚本终止:

W tensorflow/core/grappler/optimizers/data/auto_shard.cc:786] AUTO sharding policy will apply DATA sharding policy as it failed to apply FILE sharding policy because of the following reason: Found an unshardable source dataset: name: "TensorSliceDataset/_1"
op: "TensorSliceDataset"

训练代码如下:

train_ds = image_dataset_from_directory(
    self.data_dir,
    validation_split=self.val,
    subset="training",
    seed=1,
    image_size=(self.height, self.width),
    batch_size=BATCH_SIZE)

val_ds = image_dataset_from_directory(
    self.data_dir,
    validation_split=self.val,
    subset="validation",
    seed=1,
    image_size=(self.height, self.width),
    batch_size=BATCH_SIZE)

gpus = tf.config.list_logical_devices('GPU')
strategy = tf.distribute.MirroredStrategy(gpus)
with strategy.scope():
    model = Sequential([
        Conv2D(32, 3, padding='same'),
        PReLU(),
        MaxPooling2D(),
        Flatten(),
        Dense(64),
        PReLU(),
        Dense(num_classes)])
    optimizer = Adam()

    model.compile(optimizer=optimizer,
                  loss=SparseCategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])

history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=100,
)
解决方案

方案1:针对image_dataset_from_directory直接调整分片策略

这个警告的核心原因是:使用validation_split时,image_dataset_from_directory内部会通过TensorSliceDataset切分训练/验证集,导致无法应用FILE分片策略,只能自动降级为DATA分片。显式指定分片策略即可解决问题,同时不影响原有数据集构建流程:

# 创建train_ds和val_ds之后添加以下代码
options = tf.data.Options()
# 显式指定使用DATA分片策略
options.experimental_distribute.auto_shard_policy = tf.data.experimental.AutoShardPolicy.DATA
train_ds = train_ds.with_options(options)
val_ds = val_ds.with_options(options)

# 可选:添加缓存和预取优化多GPU训练效率
train_ds = train_ds.cache().prefetch(tf.data.AUTOTUNE)
val_ds = val_ds.cache().prefetch(tf.data.AUTOTUNE)

# 后续的策略定义、模型编译和训练代码保持不变

方案2:手动构建数据集(使用from_tensor_slices处理多类别目录)

如果希望彻底避免这类分片问题,可以手动遍历多类别目录生成文件路径和标签,再用from_tensor_slices构建数据集,步骤如下:

import os
import sklearn.model_selection

# 1. 遍历多类别目录,收集文件路径和对应标签
data_dir = self.data_dir
class_names = sorted(os.listdir(data_dir))
class_to_idx = {name: idx for idx, name in enumerate(class_names)}

file_paths = []
labels = []
for cls_name in class_names:
    cls_dir = os.path.join(data_dir, cls_name)
    # 获取当前类别下所有图片文件
    cls_files = tf.io.gfile.glob(os.path.join(cls_dir, "*"))
    file_paths.extend(cls_files)
    labels.extend([class_to_idx[cls_name]] * len(cls_files))

# 2. 手动划分训练和验证集
train_paths, val_paths, train_labels, val_labels = sklearn.model_selection.train_test_split(
    file_paths, labels, test_size=self.val, random_state=1
)

# 3. 定义图片加载和预处理函数
def load_and_preprocess(path, label):
    img = tf.io.read_file(path)
    # 根据图片格式调整解码方式(如decode_png)
    img = tf.image.decode_jpeg(img, channels=3)
    img = tf.image.resize(img, (self.height, self.width))
    # 可添加其他预处理(如归一化)
    return img, label

# 4. 构建数据集并优化
train_ds = tf.data.Dataset.from_tensor_slices((train_paths, train_labels))
train_ds = train_ds.map(load_and_preprocess, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.shuffle(buffer_size=len(train_paths)).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)

val_ds = tf.data.Dataset.from_tensor_slices((val_paths, val_labels))
val_ds = val_ds.map(load_and_preprocess, num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)

# 后续的策略定义、模型编译和训练代码保持不变

这种方式完全由你控制数据集的构建流程,生成的from_tensor_slices数据集可以更好地适配多GPU的分片策略,避免自动分片的警告问题。

内容的提问来源于stack exchange,提问作者justRandomLearner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 23:27:05