标记和培训Keras中的自定义层

时间:2019-08-09 10:11:40

标签: tensorflow keras

我想创建一个自定义的keras层,该层在训练过程中执行其他操作,以进行验证或测试。

from tensorflow import keras
K = keras.backend
from keras.layers import Layer
import tensorflow as tf

class MyCustomLayer(Layer):

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

    @tf.function
    def call(self, x, is_training=None):

        is_training = K.learning_phase()
        tf.print("training: ", is_training)
        if is_training is 1 or is_training is True:

            xs = x * 4
            return xs
        else:
            xs = x*0
            return xs

model = Sequential()
model.add(Dense(16, input_dim=input_dim))
model.add(MyCustomLayer(0.5))
model.add(ReLU())
model.add(Dense(32, activation='relu'))
model.add(Dense(16, activation='relu'))
model.add(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:  0
training:  0
training:  0
training:  0
training:  0
training:  0
training:  0
training:  0

有人知道如何解决此问题吗?

2 个答案:

答案 0 :(得分:0)

这里存在一些问题和误解。首先,您在kerastf.keras导入之间混合了导入,您应该只使用其中一个。其次,call的参数称为training,而不是is_training

我认为问题在于tf.print并没有真正打印training变量的值作为其张量流符号变量,并且可能间接更改值。还有其他方法可以检查图层在推理和训练期间的行为是否不同,例如:

class MyCustomLayer(Layer):

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

def call(self, inputs, training=None):

    train_x = inputs * 4
    test_x = inputs * 0

    return K.in_train_phase(train_x,
                            test_x,
                            training=training)

然后使用此模型:

model = Sequential()
model.add(Dense(1, input_dim=10))
model.add(MyCustomLayer(0.5))
model.compile(loss='mse', optimizer='adam')

并创建一个明确接收K.learning_phase()变量的函数实例:

fun = K.function([model.input, K.learning_phase()], [model.output])

如果您将Klearning_phase()设置为1或0进行调用,则会看到不同的输出:

d = np.random.random(size=(2,10))
print(fun([d, 1]))
print(fun([d, 0]))

结果:

[array([[4.1759257], [3.9988194]], dtype=float32)]
[array([[0.], [0.]], dtype=float32)]

这表明该层在训练和推理/测试期间具有不同的行为。

答案 1 :(得分:0)

所以,我只是弄清楚出了什么问题。我正在混合两种不同类型的类:

from keras import Sequential
from tensorflow import keras
K = keras.backend

因此,模型正在使用keras,而我正在从tensorflow.keras调用该标志。因此,K.learning_phase()不能按预期工作。

要修复它,我用过

from tensorflow.keras import Sequential
from tensorflow import keras
K = keras.backend