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

保存TensorFlow图像分类模型时触发AttributeError: 'CustomAugment'对象无'__name__'属性的问题咨询

问题原因与解决方法

嘿,这个问题我之前在调试TensorFlow数据增强的时候也碰到过!咱们先搞清楚为啥会报错,再一步步解决。

为什么会出现 AttributeError: 'CustomAugment' object has no attribute '__name__'?

Keras的Lambda层设计初衷是用来包装函数的,而不是类的实例。当你保存模型时,Keras需要序列化所有层的配置,对于Lambda层来说,它会依赖传入的可调用对象的__name__属性来完成序列化。

但你这里传的是CustomAugment()——这是一个类的实例,不是函数。类本身有__name__属性(比如CustomAugment.__name__会返回字符串"CustomAugment"),但类的实例是没有这个属性的,所以保存时就触发了这个错误。

另外顺便提一句,你的_color_drop函数里有个小bug:转灰度后得到的是image,但你用tf.tile的却是原输入x,等于没做颜色丢弃,后面我会在代码示例里修复这个问题。

两种解决方法

方法一:把自定义增强改成函数(最简单)

既然Lambda层适合包装函数,那我们直接把CustomAugment的逻辑改成函数形式:

def CustomAugment(image):
    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 _color_drop(x):
        # 修复bug:转灰度后tile处理后的图像,而不是原x
        gray_image = tf.image.rgb_to_grayscale(x)
        return tf.tile(gray_image, [1, 1, 3])
    
    img = _random_apply(tf.image.flip_left_right, image, p=0.6)
    img = _random_apply(_color_drop, img, p=0.9)
    return img

# Lambda层直接传入函数本身,不要实例化
data_augmentation = keras.Sequential(
    [
        tf.keras.layers.Lambda(CustomAugment),
        layers.experimental.preprocessing.RandomRotation(0.1),
    ]
)

方法二:把CustomAugment改成自定义Keras层(更规范)

如果你的增强逻辑比较复杂,或者需要保存一些参数,更推荐把它改成继承tf.keras.layers.Layer的自定义层,这样天然支持Keras的序列化和保存:

class CustomAugment(tf.keras.layers.Layer):
    def __init__(self, flip_prob=0.6, color_drop_prob=0.9, **kwargs):
        super().__init__(**kwargs)
        self.flip_prob = flip_prob
        self.color_drop_prob = color_drop_prob

    def call(self, image, training=None):
        # 可选:只在训练阶段应用增强,推理阶段返回原图
        if not training:
            return image
        
        img = self._random_apply(tf.image.flip_left_right, image, p=self.flip_prob)
        img = self._random_apply(self._color_drop, img, p=self.color_drop_prob)
        return img

    def _color_drop(self, x):
        gray_image = tf.image.rgb_to_grayscale(x)
        return tf.tile(gray_image, [1, 1, 3])  # 修复之前的bug

    def _random_apply(self, 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)
    
    # 必须实现这个方法,让Keras能序列化层的参数
    def get_config(self):
        config = super().get_config()
        config.update({
            'flip_prob': self.flip_prob,
            'color_drop_prob': self.color_drop_prob
        })
        return config

# 现在直接用这个层,不需要Lambda包装
data_augmentation = keras.Sequential(
    [
        CustomAugment(),
        layers.experimental.preprocessing.RandomRotation(0.1),
    ]
)

这两种方法都能解决模型保存时的错误,第二种方法更适合长期维护的项目,因为自定义层的扩展性更好,也符合Keras的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 20:17:38