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

Keras自定义层训练与测试阶段行为异常问题求助

解决Keras自定义层训练/测试阶段行为不一致的问题

这个问题我之前也碰到过,核心是你没有正确处理Keras传递的training参数,以及对TensorFlow张量的判断方式有误。让我一步步帮你修正:

问题根源分析

  1. 错误覆盖training参数:你在call方法里手动赋值is_training = K.learning_phase(),但Keras在调用层时会自动传入training参数(注意参数名是training而非is_training),手动获取的K.learning_phase()在tf.function下会变成符号张量,无法用Python的is判断。
  2. 张量判断方式错误:is_training is 1或is_training is True这种写法对TensorFlow张量无效——张量是特殊对象,不是Python原生的整数/布尔值,所以这个判断永远为False,导致你始终进入测试分支。
  3. 导入不统一:同时使用from tensorflow import keras和from keras.layers import Layer可能引发版本冲突,建议统一使用tensorflow.keras的导入。

修正后的自定义层代码

推荐两种写法,任选其一即可:

方法1:使用tf.cond显式分支(更灵活)

这种写法适合需要执行复杂分支逻辑的场景:

import tensorflow as tf
from tensorflow.keras import layers, Sequential
from tensorflow.keras.regularizers import l2

class MyCustomLayer(layers.Layer):
    def __init__(self, ratio=0.5, **kwargs):
        self.ratio = ratio
        super().__init__(**kwargs)

    def call(self, x, training=None):
        # 如果training未传入,自动获取当前学习阶段
        if training is None:
            training = tf.keras.backend.learning_phase()
        
        # 定义训练和测试阶段的操作
        def train_operation():
            tf.print("training: ", True)
            return x * 4
        
        def test_operation():
            tf.print("training: ", False)
            return x * 0
        
        # 根据training状态选择执行哪个操作
        return tf.cond(training, train_operation, test_operation)

方法2:使用in_train_phase简化代码(适合简单逻辑)

Keras提供了in_train_phase工具函数,直接帮你处理分支逻辑:

import tensorflow as tf
from tensorflow.keras import layers, Sequential
from tensorflow.keras.regularizers import l2
from tensorflow.keras import backend as K

class MyCustomLayer(layers.Layer):
    def __init__(self, ratio=0.5, **kwargs):
        self.ratio = ratio
        super().__init__(**kwargs)

    def call(self, x, training=None):
        tf.print("training: ", training)
        # 第一个参数是训练阶段的输出,第二个是测试/验证阶段的输出
        return K.in_train_phase(x * 4, x * 0, training=training)

完整的模型训练代码

把修正后的层代入你的模型:

# 假设你已经定义了input_dim, output_dim, X_train, y_train
model = Sequential()
model.add(layers.Dense(16, input_dim=input_dim))
model.add(MyCustomLayer(0.5))
model.add(layers.ReLU())
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(output_dim, activation='softmax', kernel_regularizer=l2(0.01)))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train, y_train, validation_split=0.05, epochs=5)

现在运行代码,你会看到训练阶段打印training: True,验证阶段打印training: False,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:46:35