TensorFlow TFDS数据加载阶段数据增强报错TypeError/AttributeError求助
问题根因
- 核心错误1:
_random_apply要求第一个参数是可调用的函数对象,但你传入的是tf.image.flip_left_right(image)这类执行后返回的张量,程序尝试把张量当函数调用就会抛出Tensor不可调用的报错。 - 核心错误2:
tf.data.Dataset.map默认在TensorFlow图模式下执行,图模式下的张量没有numpy()方法,强行调用就会出现属性不存在的报错,所有数据增强操作直接用TF原生张量操作即可,完全不需要转numpy数组。 - 遍历数据集时报错的原因还是核心错误1没有彻底解决,你传给
_random_apply的第一个参数仍然是执行后的张量,不是可调用函数。
修复后的完整代码
def _random_apply(func, x, p): return tf.cond(tf.less(tf.random.uniform([], minval=0, maxval=1, dtype=tf.float32), tf.cast(p, tf.float32)), lambda: func(x), lambda: x) def _resize_with_pad(image): # 直接使用TF原生操作,返回张量即可 return tf.image.resize_with_pad(image, target_height=IMG_S, target_width=IMG_S) def augment(image, label): # 第一个参数传函数对象本身,不要提前调用执行 img = _random_apply(tf.image.flip_left_right, image, p=0.2) img = _random_apply(_resize_with_pad, img, p=1) return img, label train_dataset = ( train_ds .shuffle(1000) .map(augment, num_parallel_calls=tf.data.AUTOTUNE) .prefetch(tf.data.AUTOTUNE) )
补充说明
- 如果需要传入的函数有额外参数,用lambda包装即可,比如要调用带自定义参数的处理函数,可以写
lambda x: tf.image.random_brightness(x, max_delta=0.2)作为第一个参数传给_random_apply。 - 所有在
tf.data.Dataset.map中调用的函数,尽量都使用TensorFlow原生操作实现,不要转numpy数组,避免图模式执行报错。
内容的提问来源于stack exchange,提问作者JKnecht
相关产品推荐
相关产品推荐

