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

使用tf.keras.utils.image_dataset_from_directory自定义CSV标签报错求助

问题分析与解决方案

错误根源

你遇到的问题核心在于tf.keras.utils.image_dataset_from_directory的labels参数与validation_split配合时的底层逻辑冲突:

  1. 当传入自定义标签(非'inferred'/None)时,要求标签长度必须与目录内图片数量严格匹配,且格式需为numpy数组或普通列表(而非Tensor)。
  2. 使用validation_split时,函数会自动划分数据集,但如果传入的是Tensor类型的标签,内部切片转换时会触发类型不兼容错误。

此外,直接传入整数列表作为标签报错,大概率是因为顺序与函数默认的文件名排序不匹配,或者未转为numpy数组导致处理异常。

推荐解决方案:手动构建tf.data.Dataset

由于你的图片未按类别拆分,用tf.data.Dataset手动构建数据集更灵活可控,完全避免image_dataset_from_directory的限制。

步骤1:准备图片路径与标签

首先确保图片路径顺序与你的label_int完全对应:

import os
import numpy as np
import tensorflow as tf

# 配置参数
train_dir = "你的训练图片目录路径"
batch_size = 32
img_height = 224
img_width = 224
cat_count = 120

# 获取所有图片路径(按文件名排序,与label_int顺序对齐)
image_paths = sorted([
    os.path.join(train_dir, fname) 
    for fname in os.listdir(train_dir) 
    if fname.endswith(('.jpg', '.jpeg', '.png'))
])

# 验证路径数量与标签数量匹配
assert len(image_paths) == len(label_int), "图片数量与标签数量不匹配!"

步骤2:定义图片加载预处理函数

def load_and_preprocess_image(path):
    # 读取图片
    img = tf.io.read_file(path)
    # 解码为RGB格式
    img = tf.image.decode_jpeg(img, channels=3)
    # 调整尺寸
    img = tf.image.resize(img, (img_height, img_width))
    # 可选:根据模型需求添加预处理(比如归一化)
    img = tf.keras.applications.resnet50.preprocess_input(img)
    return img

情况1:标签编码(用于SparseCategoricalCrossentropy)

# 构建图片数据集
img_ds = tf.data.Dataset.from_tensor_slices(image_paths)\
    .map(load_and_preprocess_image, num_parallel_calls=tf.data.AUTOTUNE)

# 构建整数标签数据集
label_ds = tf.data.Dataset.from_tensor_slices(np.array(label_int))

# 合并图片与标签
full_ds = tf.data.Dataset.zip((img_ds, label_ds))

# 划分训练/验证集
val_size = int(0.2 * len(image_paths))
train_ds = full_ds.skip(val_size)\
    .shuffle(buffer_size=1000)\
    .batch(batch_size)\
    .prefetch(tf.data.AUTOTUNE)

val_ds = full_ds.take(val_size)\
    .batch(batch_size)\
    .prefetch(tf.data.AUTOTUNE)

情况2:独热编码(用于CategoricalCrossentropy)

# 生成独热编码的numpy数组
oh_labels = tf.one_hot(np.array(label_int), cat_count).numpy()

# 构建独热标签数据集
label_ds = tf.data.Dataset.from_tensor_slices(oh_labels)

# 合并图片与标签
full_ds = tf.data.Dataset.zip((img_ds, label_ds))

# 划分训练/验证集(同标签编码逻辑)
val_size = int(0.2 * len(image_paths))
train_ds = full_ds.skip(val_size)\
    .shuffle(buffer_size=1000)\
    .batch(batch_size)\
    .prefetch(tf.data.AUTOTUNE)

val_ds = full_ds.take(val_size)\
    .batch(batch_size)\
    .prefetch(tf.data.AUTOTUNE)

关于labels=None的补充说明

如果设置labels=None,数据集只会返回图片张量,此时你可以在model.fit()中手动传入标签,但必须严格保证:

  1. 训练数据的batch顺序与标签数组的顺序完全一致
  2. 标签数组的长度与训练数据的样本数完全匹配
    这种方式容易出现对齐错误,不推荐使用。

内容的提问来源于stack exchange,提问作者John G.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 10:24:09